-
java调用go语言_【go语言专题】JAVA&GO通过GRPC互相调用
2021-03-04 09:08:10文章目录简介JAVA提供`provider`和`consumer``proto`文件介绍java grpc providerjava grpc consumergo提供`provider`和`consumer`生成grpc文件go grpc providergo grpc consumer测试java 提供grpc服务go 提供grpc...文章目录
简介
JAVA提供`provider`和`consumer`
`proto`文件介绍
java grpc provider
java grpc consumer
go提供`provider`和`consumer`
生成grpc文件
go grpc provider
go grpc consumer
测试
java 提供grpc服务
go 提供grpc服务
参考
简介
语言中立,支持多种语言;
基于 IDL 文件定义服务,通过 proto3 工具生成指定语言的数据结构、服务端接口以及客户端 Stub;
通信协议基于标准的 HTTP/2 设计,支持双向流、消息头压缩、单 TCP 的多路复用、服务端推送等特性,这些特性使得 gRPC 在移动端设备上更加省电和节省网络流量;
序列化支持 PB(Protocol Buffer)和 JSON,PB 是一种语言无关的高性能序列化框架,基于 HTTP/2 + PB, 保障了 RPC 调用的高性能。
JAVA提供provider和consumer
proto文件介绍
syntax
指定语言版本
syntax
指定语言版本
option
修改配置选项
service
声明一个服务
rpc
声明一个方法
resturns
方法的返回值
message
定义一个消息类型
repeated
数组
stream
用流来交互
一个栗子,helloworld.proto:
syntax = "proto3"; //语法声明
// Greeter 微服务
service Greeter {
// Sends a greeting
rpc SayHello (HelloRequest) returns (HelloReply) {}
}
// HelloRequest 请求数据格式
message HelloRequest {
string name = 1;
}
// HelloReply 响应数据格式
message HelloReply {
string message = 1;
}
java grpc provider
创建fast-common-grpc-proto,用来生成grpc相关接口。依赖如下,这个还配置了build,可以通过编译生成相关接口。
com.google.protobuf
protobuf-java
${protobuf.version}
io.grpc
grpc-netty
${grpc.version}
io.grpc
grpc-protobuf
${grpc.version}
io.grpc
grpc-stub
${grpc.version}
kr.motd.maven
os-maven-plugin
${os-maven-plugin.version}
org.xolstice.maven.plugins
protobuf-maven-plugin
${protobuf-maven-plugin.version}
com.google.protobuf:protoc:${protoc.version}:exe:${os.detected.classifier}
grpc-java
io.grpc:protoc-gen-grpc-java:${grpc.version}:exe:${os.detected.classifier}
compile
compile-custom
把上面的helloworld.proto复制到 java/main/proto下,注意一定要是proto文件夹,点击compile会成生成grpc接口文件
将文件GreeterGrpc、Helloworld复制到grpc包下面,创建GreeterServer文件
GreeterServer的代码如下,继承 GreeterGrpc.GreeterImplBase 重写里面的sayHello方法
@Component
public class GreeterServer extends GreeterGrpc.GreeterImplBase implements InitializingBean {
@Value("${gRPC.port}")
private int port;
@Override
public void afterPropertiesSet() throws Exception {
ServerBuilder.forPort(port)
.addService(new GreeterServer())
.build()
.start();
}
@Override
public void sayHello(Helloworld.HelloRequest request,
io.grpc.stub.StreamObserver responseObserver) {
Helloworld.HelloReply result = Helloworld.HelloReply.newBuilder().setMessage(request.getName()).build();
responseObserver.onNext(result);
responseObserver.onCompleted();
}
}
java grpc consumer
创建SimpleClient,调用你想要调用的接口。
controller和service的代码这里就不给出了。需要的可以看github的代码,后面会给出地址。
go提供provider和consumer
生成grpc文件
在根目录下运行命令
protoc -I helloworld/ helloworld/helloworld.proto --go_out=plugins=grpc:helloworld
go grpc provider
创建service.go,代码如下
package main
import (
"context"
pb "go-grpc/helloworld"
"log"
"net"
"google.golang.org/grpc"
"google.golang.org/grpc/reflection"
)
const (
port = ":50051"
)
type server struct{} //服务对象
// SayHello 实现服务的接口 在proto中定义的所有服务都是接口
func (s *server) SayHello(ctx context.Context, in *pb.HelloRequest) (*pb.HelloReply, error) {
return &pb.HelloReply{Message: "Hello " + in.Name}, nil
}
func main() {
lis, err := net.Listen("tcp", port)
if err != nil {
log.Fatalf("failed to listen: %v", err)
}
s := grpc.NewServer() //起一个服务
pb.RegisterGreeterServer(s, &server{})
// 注册反射服务 这个服务是CLI使用的 跟服务本身没有关系
reflection.Register(s)
if err := s.Serve(lis); err != nil {
log.Fatalf("failed to serve: %v", err)
}
}
go grpc consumer
创建client.go,代码如下:
package main
import (
"context"
"log"
"os"
"time"
pb "go-grpc/helloworld"
"google.golang.org/grpc"
)
const (
address = "localhost:50051"
defaultName = "world"
)
func main() {
//建立链接
conn, err := grpc.Dial(address, grpc.WithInsecure())
if err != nil {
log.Fatalf("did not connect: %v", err)
}
defer conn.Close()
c := pb.NewGreeterClient(conn)
// Contact the server and print out its response.
name := defaultName
if len(os.Args) > 1 {
name = os.Args[1]
}
// 1秒的上下文
ctx, cancel := context.WithTimeout(context.Background(), time.Second)
defer cancel()
r, err := c.SayHello(ctx, &pb.HelloRequest{Name: name})
if err != nil {
log.Fatalf("could not greet: %v", err)
}
log.Printf("Greeting: %s", r.Message)
}
测试
接下来测试服务之间的调用
java 提供grpc服务
java调用java,启动java服务,运行FastCommonGrpcExampleApplication这个类,访问http://localhost:8080/hello
go 调用java,运行client.go会看到输出
go 提供grpc服务
java 调用go ,注释掉GreeterServer,启动FastCommonGrpcExampleApplication,启动service.go,访问http://localhost:8080/hello
go调用go,运行client.go会看到输出
go地址:https://github.com/fafeidou/go-grpc
java地址:https://github.com/fafeidou/fast-cloud-nacos
参考
java grpc: https://www.cnblogs.com/gutousu/p/9951956.html
入门及服务端创建和调用原理: https://www.cnblogs.com/wxlevel/p/9154246.html#auto_id_24
grpc(3):使用 golang 开发 grpc 服务端和客户端 : https://blog.csdn.net/freewebsys/article/details/59483427
gRPC基于Golang和Java的简单实现: https://www.jianshu.com/p/21d5d7624951
-
Android java调用go语言,.go文件生成android调用的aar包
2018-10-09 18:26:19Go语言专门针对多处理器系统应用程序的编程进行了优化,使用Go编译的程序可以媲美C或C++代码的速度,而且更加安全、支持并行进程。 想要运用androidstudio调用.go文件中的方法,具体操作如下: 1.安装go环境...Go语言专门针对多处理器系统应用程序的编程进行了优化,使用Go编译的程序可以媲美C或C++代码的速度,而且更加安全、支持并行进程。
想要运用androidstudio调用.go文件中的方法,具体操作如下:
1.安装go环境(mac系统)
(1)安装Homebrew命令: ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
(2)使用brew安装go命令:brew install go
(3)使用go env查看当前go版本,以及路径配置相关属性,记住GOROOT的值下面会用到。
(4)修改go路径环境:
主要是GOROOT和GOPATH
GOROOT:就是go的安装环境
GOPATH:作为编译后二进制的存放目的地和import包时的搜索路径。其实说通俗点就是你的go项目工作目录。通常情况下GOPATH包含三个目录:bin、pkg、src。(src目录下主要存放go的源文件;pkg目录存放编译好的库文件,主要是*.a文件;bin目录主要存放可执行文件)
那么重点操作来了,使用命令:vim ~/.bash_profile
现在已经进入了文件中,输入
-
GOROOT=上面记录的值
-
export GOROOT
-
export GOPATH=在你的目录中建立一个go环境目录,如mygopath
-
export GOBIN=$GOPATH/bin
-
export PATH=$PATH:$GOBIN:$GOROOT/bin
编辑完之后退出保存文件,然后使用命令source ~/.bash_profile
使之生效,然后再使用命令go env查看当前环境,可以发现已经是你配置文件中设置的路径环境了。
2.安装gomobile环境
(1)安装gomobile命令:go get golang.org/x/mobile/cmd/gomobile(可能需要翻墙)
(2)go配置android sdk环境变量,输入命令:export ANDROID_HOME=你的sdk路径,可以在androidstudio中local.properties中查看
(3)gomobile初始化ndk,执行命令:gomobile init -ndk 你的ndk路径,同上可以找到
(4)如上所说,建立自己的gopath目录,gopath目录下面有src,bin,pkg三个文件夹,在src下建一个文件夹hello,名字随意,将你要使用的.go文件放到hello中。
(5)见证奇迹的时刻到了,进入到gopath目录中的bin目录下执行命令:cd 你的gopath路径 + "/bin" ,然后输入命令:
gomobile bind -target=android hello,只需等待几十秒就会在gopath的bin目录中生成.aar文件,这个文件android端就可以使用了。
3.androidstudio调用生成的.aar文件。
(1)androidstudio新建一个工程
(2)将生成的.aar文件放到libs下面
(3)在你的app下面的build.gradle中加入如下代码即可
repositories { flatDir { dirs 'libs' //this way we can find the .aar file in libs folder } }
dependencies { compile (name:'tudun', ext:'aar') }
大功告成,现在重新编译就可以调用go中的方法了,是不是很简单,只要一步一步按照命令操作即可!
-
-
java调用go接口_go语言调用API实线分词
2021-03-14 19:55:231、确保已经安装go语言 2、代码实现B.代码:packagepullwordimport("bufio""fmt""net""strings")typerequeststruct{sourcestringparam1float32param2uint}funcNewRequest(sourcestring,thresholdfloat32,debugbool)...1、确保已经安装go语言
2、代码实现
B.代码:
package pullword
import (
"bufio"
"fmt"
"net"
"strings"
)
type request struct {
source string
param1 float32
param2 uint
}
func NewRequest(source string, threshold float32, debug bool) request {
var param2 uint
if debug {
param2 = 1
} else {
param2 = 0
}
return request{
source: source,
param1: threshold,
param2: param2,
}
}
func (req request) Do() ([]string, error) {
conn, err := net.Dial("tcp", "api.pullword.com:2015")
if err != nil {
return nil, err
}
writer := bufio.NewWriter(conn)
_, err = writer.WriteString(fmt.Sprintf("%s\t%1.2f\t%d]\r\n", req.source, req.param1, req.param2))
if err != nil {
return nil, err
}
writer.Flush()
if err != nil {
return nil, err
}
scanner := bufio.NewScanner(conn)
list := make([]string, 0)
for scanner.Scan() {
if scanner.Text() != "\r\n" && scanner.Text() != "" {
list = append(list, strings.Trim(scanner.Text(), "\r\n"))
}
}
if err := scanner.Err(); err != nil {
return nil, err
}
return list, nil
}
package main
import (
"fmt"
"os"
"pullword"
"io/ioutil"
)
func main() {
result_str := ""
result_str = readFile("/home/tian/Desktop/test.txt")
req := pullword.NewRequest(result_str, 1, true)
result, err := req.Do()
if err != nil {
panic(err)
}
fmt.Printf("%q", result)
}
func readFile(path string) string {
fi,err := os.Open(path)
if err != nil{panic(err)}
defer fi.Close()
fd,err := ioutil.ReadAll(fi)
return string(fd)
}
test.txt
你的姿势水平还远远不够
C.运行结果:
["姿势:1" "水平:1" "远远:1" "不够:1"]
-
java 调用 go_实践总结:在 Java 中调用 Go 代码
2021-02-28 17:10:41java整个过程要解决的问题主要两个:数据类型在两种语言中如何转化何时清理无用的数据下面就围绕上述调用过程来阐述,本文涉及代码完整版可以下面链接找到:Go -> Cgo这是跨语言调用的第一步,主要是借助 cgo,...在 Java 中调用 Go 的大致过程如下go --> cgo --> jna --> java
整个过程要解决的问题主要两个:数据类型在两种语言中如何转化
何时清理无用的数据
下面就围绕上述调用过程来阐述,本文涉及代码完整版可以下面链接找到:
Go -> Cgo
这是跨语言调用的第一步,主要是借助 cgo,把 Go 代码编译 C 共享库。
cgo 是 Go 语言提供与 C 语言互调的一工具。提供一个名为 C 的伪 package,供 Go 访问 C 中的变量与函数,如 C.size_t C.stdout 等;同时提供 5 个特殊函数,用于两种语言间类型的转化:// Go string to C string
// The C string is allocated in the C heap using malloc.
// It is the caller's responsibility to arrange for it to be
// freed, such as by calling C.free (be sure to include stdlib.h
// if C.free is needed).
func C.CString(string) *C.char
// Go []byte slice to C array
// The C array is allocated in the C heap using malloc.
// It is the caller's responsibility to arrange for it to be
// freed, such as by calling C.free (be sure to include stdlib.h
// if C.free is needed).
func C.CBytes([]byte) unsafe.Pointer
// C string to Go string
func C.GoString(*C.char) string
// C data with explicit length to Go string
func C.GoStringN(*C.char, C.int) string
// C data with explicit length to Go []byte
func C.GoBytes(unsafe.Pointer, C.int) []byte
需要注意一点,cgo 中函数不能直接返回 slice/map 等具有 go pointer (区别与 C pointer,由 go runtime 管理生命周期)的数据类型,否则会报下面的 panic 信息:panic: runtime error: cgo result has Go pointer
原因也很简单,go 是有 gc 的,假如允许返回具有 go pointer 的数据,那么 C 代码中得到的数据无法保证合法性,很有可能已经被 gc 了,即悬挂指针问题。解决的方式也很简单,就是采用 go 提供的特殊转化函数,将数据转为 unsafe.Pointer,在 C 中用 void * 的方式去使用。
可以想象,这些特殊转化函数一定对数据进行了深拷贝,来保证数据的合法性,可参考 C.CBytes 的定义const cBytesDef = `
func _Cfunc_CBytes(b []byte) unsafe.Pointer {
p := _cgo_cmalloc(uint64(len(b)))
pp := (*[1<<30]byte)(p)
copy(pp[:], b)
return p
}
`
但这也意味着,Go/C 代码中需要负责 free 掉无用的数据(至于哪边 free,要看实际情况)。示例:func main() {
cs := C.CString("Hello from stdio")
C.myprint(cs)
C.free(unsafe.Pointer(cs))
}
将 Go 函数导出供 C 调用,需要用 //export 标示相关函数,并且 Go 文件需要在 package main下。然后用类似下面的 build 命令,即可得到与 C 互调的动态库,同时会生产一个头文件,里面有 export 函数的相关签名。# linux 下可输出到 libawesome.so,这里以 Mac 下的动态库为例
go build -v -o libawesome.dylib -buildmode=c-shared ./main.go//export Hello
func Hello(msg string) *C.char {
return C.CString("hello " + strings.ToUpper(msg))
}
// 头文件中 Hello 的定义
// ptrdiff_t is the signed integer type of the result of subtracting two pointers.
// n 这里表示字符串的长度
typedef struct { const char *p; ptrdiff_t n; } _GoString_;
extern char* Hello(GoString p0);
Cgo -> JNA
这一步主要是 Java 中如何调用 C 代码,目前主要有两种方式,JNA,优势是调用方便,只需要编写 Java 代码,JNA 框架负责在 C/Java 中进行数据类型转化
JNI,优势是性能好,缺点是调用繁琐
详细区别这里不展开叙述,感兴趣的读者可参考下面文章:
JNA -> Java
这一步主要是在 Java 代码中如何调用 JNA 框架提供的库进行跨语言调用,也是本文的重点。
JNA 将 Java 基本类型直接映射为 C 中同等大小的类型,这里摘抄如下Native TypeSizeJava TypeCommon Windows Typeschar8-bit integerbyteBYTE, TCHAR
short16-bit integershortWORD
wchar_t16/32-bit charactercharTCHAR
int32-bit integerintDWORD
intboolean valuebooleanBOOL
long32/64-bit integerNativeLongLONG
long long64-bit integerlong__int64
float32-bit FPfloat
double64-bit FPdouble
char*C stringStringLPCSTR
void*pointerPointerLPVOID, HANDLE, LPXXX
对于 C 中的 struct/pointer,JNA 中也提供了 Structure/Pointer 类来对应。JNA 的具体使用过程可参考:
上述 GettingStarted 中第三种加载动态库的方式(即 resources 下的 {OS}-{ARCH}/{LIBRARY} 目录内)可以把动态库一起打包到 jar 中,这对于提供基础类库时比较方便,用户不需要再额外配置。resources/
├── darwin
│ └── libawesome.dylib
├── linux-x86-64
│ └── libawesome.so
vladimirvivien/go-cshared-examples 这个仓库演示了四个函数 Add/Cosine/Sort/Log 的 JNA 调用,但这四个函数的返回类型都是基本类型(int/float64),没有 string/slice 等复杂类型,因此这里通过五个示例讲述复杂类型的返回问题:BadStringDemo.java 本示例演示了网络上一种常见,但有内存泄露问题的返回 string 的方式
GoodStringDemo.java 这个示例演示了如何正确的返回 string
ReturnByteSliceDemo.java 本示例演示如何返回 slice,以及如何在 Java 中处理 Go 中的多个返回值
ReturnInterfaceDemo.java 本示例演示返回具有 Go Pointer 的结构时的报错行为
上述示例均使用 direct mapping 的方式做 JNA,这种方式性能更好,但是支持的参数类型有限,读者可参考 vladimirvivien/go-cshared-examples 学习 interface mapping 的使用方式。
总结
C 语言作为连接不同高级语言的胶水语言,不具备垃圾回收功能,所以开发者在做 JNA 时要注意回收无用的内存结构。
参考
-
用Go语言写Android应用 (2) - 从Android的Java调用Go代码
2016-07-12 01:36:47用Go语言写Android应用 (2) - 从Android的Java调用Go代码 上一篇我们讲到,Go在Android中的作用,就相当于NDK中的C/C++。上节我们学习了参照NDK的方式用纯Go语言来写应用。但是,也正如在Android中,C/C++主要是通过... -
golang调用java_Go语言通过JNI调用java的方法
2021-03-06 17:41:28最近有一个问题,是在golang作为底层,想获取apk的版本号和版本号代码(通俗一点就是versionName和versionCode),如果这时java代码,可以很容易地通过// please add try/catch ... ;-)PackageInfo info = context.... -
go语言如何调用java接口_Go语言实现的Java Stream API
2021-03-22 09:52:18学习Go语言时实现的集合操作工具库,类似于Java 8 中新增的Stream API。由于Go语言不支持泛型,所以基于反射实现。只用于学习目的,不要用于生产(PS:当然也不会有人用)。集合操作包括生成操作、中间操作和终止操作。... -
java调用百度翻译_Java调用百度API实现翻译-Go语言中文社区
2021-02-12 20:52:40下面是Java调用百度API实现翻译的具体步骤:一、在写代码之前先在在百度翻译平台中,申请APP_ID申请地址申请的详见点击打开链接申请之后,会得到APP_ID和SECURITY_KEY二、java代码如下import IJFrame.IJFrame;... -
go语言如何调用java接口_Go调用Java的一个简单例子-Go语言中文社区
2021-03-17 18:49:05由于Java世界里有非常丰富的开源应用模型和轮子,而这些正是Go世界里面最缺乏的东西,所以我首先考虑的就是如何在Go里面调用现有的Java代码。早上写了个简单的Go调用Java的例子,在winxp环境下能够正常运行。这段... -
java调用go动态库_golang开发android应用(二) - go语言生成android动态库
2021-03-16 22:45:28063666765/android/src/main/java/go/Universe.java write /tmp/gomobile-work-063666765/android/src/main/java/go/error.java write /tmp/gomobile-work-063666765/gomobile_bind/java_universe.c write /tmp/... -
java客户端go服务端_Java客户端调用Python服务-Go语言中文社区
2021-03-17 18:02:51Java客户端调用Python服务端某些大型web服务一般是采用Spring框架编写的,然而深度学习计算框架TensorFlow是采用Python编写的,那么如何让客户端调用Python服务端的计算资源返回结果呢,一种可以采用传统的... -
python如何调用java语言_使用python调用java-jpype-Go语言中文社区
2020-12-28 21:26:22'build/jar') #startJVM(r"D:worktoolsJavajdk1.5jrebinserverjvm.dll", "-ea") jpype.java.lang.System.out.println("Hello World") jpype.shutdownJVM() 直接在cmd命令行执行python test.py就可以了 二、调用jar... -
java调用restful接口_Java调用RESTful接口的几种方式-Go语言中文社区
2021-02-12 11:35:59前端一般通过Ajax来调用,后端调用的方式还是挺多的,比如HttpURLConnection,HttpClient,Spring的RestTemplate服务端代码如下:package com.demo.restful.service.impl;import com.demo.restful.model.User;import... -
java为啥不能调用go脚本_实践总结:在 Java 中调用 Go 代码
2021-03-08 23:37:33java整个过程要解决的问题主要两个:数据类型在两种语言中如何转化何时清理无用的数据下面就围绕上述调用过程来阐述,本文涉及代码完整版可以下面链接找到:Go -> Cgo这是跨语言调用的第一步,主要是借助 cgo,... -
【go语言专题】JAVA&GO通过GRPC互相调用
2020-01-03 11:57:24文章目录简介JAVA提供`provider`和`consumer``proto`文件介绍java grpc providerjava grpc consumergo提供`provider`和`consumer`生成grpc文件go grpc providergo grpc consumer测试java 提供grpc服务go 提供grpc... -
java 调用 go rpcx_rpcx+zipkin
2021-03-21 10:45:08最近工作中常用到golang,学习了下golang的rpc框架,目前比较流行的有1.rpcx(http://rpcx.site/) 类似dubbo,不用定义protobuf文件 ...),服务拆分之后就会带来一个很基础的问题:调用链追踪,这个对于追踪问题和... -
java 调用 go rpcx_Rpcx源码之网关Gateway
2021-03-13 11:46:16一、rpcx中的网关在使用rpcx过程中可能会存在其他语言比如Java、Python、C#等来调用rpcx服务,这意味着需要提供不同的rpcx的协议来支撑,不过rpcx目前已提供了GateWay来为对应的rpcx服务提供了http网关服务,直接... -
java web短信接口_Java调用WebService短信接口-Go语言中文社区
2021-02-28 11:23:04二、Java代码,其中的MD5工具类请参照我的其他文章,或自己找一个MD5加密工具类。最终的MD5结果为32为大写。public class SendSMS {//短信接口地址private static String Url = "http://sdk.entinfo.cn:...