Go语言高级编程

324课时
1.4K学过
8分

2. 第2章 CGO编程

引言

2.1 快速入门

2.1.1 最简CGO程序

2.1.2 基于C标准库函数输出字符串

2.1.3 使用自己的C函数

2.1.4 C代码的模块化

2.1.5 用Go重新实现C函数

2.1.6 面向C接口的Go编程

2.2 CGO基础

2.2.1 import "C"语句

2.2.2 #cgo语句

2.2.3 build tag 条件编译

2.3 类型转换

2.3.1 数值类型

2.3.2 Go 字符串和切片

2.3.3 结构体、联合、枚举类型

2.3.4 数组、字符串和切片

2.3.5 指针间的转换

2.3.6 数值和指针的转换

2.3.7 切片间的转换

2.4 函数调用

2.4.1 Go调用C函数

2.4.2 C函数的返回值

2.4.3 void函数的返回值

2.4.4 C调用Go导出函数

2.5 内部机制

2.5.1 CGO生成的中间文件

2.5.2 Go调用C函数

2.5.3 C调用Go函数

2.6 实战: 封装qsort

2.6.1 认识qsort函数

2.6.2 将qsort函数从Go包导出

2.6.3 改进:闭包函数作为比较函数

2.6.4 改进:消除用户对unsafe包的依赖

2.7 CGO内存模型

2.7.1 Go访问C内存

2.7.2 C临时访问传入的Go内存

2.7.3 C长期持有Go指针对象

2.7.4 导出C函数不能返回Go内存

2.8 C++ 类包装

2.8.1 C++ 类到 Go 语言对象

2.8.1.1 准备一个 C++ 类

2.8.1.2 用纯C函数接口封装 C++ 类

2.8.1.3 将纯C接口函数转为Go函数

2.8.1.4 包装为Go对象

2.8.2 Go 语言对象到 C++ 类

2.8.2.1 构造一个Go对象

2.8.2.2 导出C接口

2.8.2.3 封装C++对象

2.8.2.4 封装C++对象改进

2.8.3 彻底解放C++的this指针

2.9 静态库和动态库

2.9.1 使用C静态库

2.9.2 使用C动态库

2.9.3 导出C静态库

2.9.4 导出C动态库

2.9.5 导出非main包的函数

2.10 编译和链接参数

2.10.1 编译参数:CFLAGS/CPPFLAGS/CXXFLAGS

2.10.2 链接参数:LDFLAGS

2.10.3 pkg-config

2.10.4 go get 链

2.10.5 多个非main包中导出C函数

课程评价 (0)

请对课程作出评价:
0/300

学员评价

暂无精选评价
20分钟

4.7.1 Protobuf扩展语法

目前Protobuf相关的很多开源项目都使用到了Protobuf的扩展语法。在前一节中提到的验证器就是通过给结构体成员增加扩展元信息实现验证。在grpc-gateway项目中,则是通过为服务的每个方法增加Http相关的映射规则实现对Rest接口的支持。pbgo也是通过Protobuf的扩展语法来为rest接口增加元信息。

pbgo的扩展语法在github.com/chai2010/pbgo/pbgo.proto文件定义:

syntax = "proto3";
package pbgo;

option go_package = "github.com/chai2010/pbgo;pbgo";

import "google/protobuf/descriptor.proto";

extend google.protobuf.MethodOptions {
	HttpRule rest_api = 20180715;
}

message HttpRule {
	string get = 1;
	string put = 2;
	string post = 3;
	string delete = 4;
	string patch = 5;
}

pbgo.proto文件是pbgo框架的一个部分,需要被其他的proto文件导入。Protobuf本身自有一套完整的包体系,在这里包的路径就是pbgo。Go语言也有自己的一套包体系,我们需要通过go_package的扩展语法定义Protobuf和Go语言之间包的映射关系。定义Protobuf和Go语言之间包的映射关系之后,其他导入pbgo.ptoto包的Protobuf文件在生成Go语言时,会生成pbgo.proto映射的Go语言包路径。

Protobuf扩展语法有五种类型,分别是针对文件的扩展信息、针对message的扩展信息、针对message成员的扩展信息、针对service的扩展信息和针对service方法的扩展信息。在使用扩展前首先需要通过extend关键字定义扩展的类型和可以用于扩展的成员。扩展成员可以是基础类型,也可以是一个结构体类型。pbgo中只定义了service的方法的扩展,只定义了一个名为rest_api的扩展成员,类型是HttpRule结构体。

定义好扩展之后,我们就可以从其他的Protobuf文件中使用pbgo的扩展。创建一个hello.proto文件:

syntax = "proto3";
package hello_pb;

import "github.com/chai2010/pbgo/pbgo.proto";

message String {
	string value = 1;
}

service HelloService {
	rpc Hello (String) returns (String) {
		option (pbgo.rest_api) = {
			get: "/hello/:value"
		};
	}
}

首先我们通过导入github.com/chai2010/pbgo/pbgo.proto文件引入扩展定义,然后在HelloService的Hello方法中使用了pbgo定义的扩展。Hello方法扩展的信息表示该方法对应一个REST接口,只有一个GET方法对应"/hello/:value"路径。在REST方法的路径中采用了httprouter路由包的语法规则,":value"表示路径中的该字段对应的是参数中同名的成员。