Go 基础语法4(RPC、Context、包依赖、docker 部署、安装 gin 框架)

12. RPC;

12.1 创建 rpc 服务和调用;

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

GO 自带的 RPC 包

// 包:net/rpc
// 基于tcp,且使用 socket,所以必须创建一个socket服务端(使用tcp的方式)
 lis,err := net.Listen("tcp",":8082") 

// 创建一个struct,基本规则如下
// 1. 方法可导出(首字母大写)
// 2. 方法有两个参数,都是可导出类型或内建类型
// 3. 方法的第二个参数是指针类型:第一个参数是接收的参数,第二个参数是返回的参数(客户端得到的值)
// 4. 函数有error返回
type UserService struct {
}

func(this *UserService) GetUser(userid int ,username *string) error  {
	 if userid == 101{
	 	*username = "vip"
	 }else{
	 	*username = "guest"
	 }
	 return nil
}
 
// 注册:
rpc.Register(new(UserService))

// 接受客户端连接
rpc.Register(new(UserService))
  • 文件 /Users/go/src/com.net/myrpcserver/main.go
package main

import (
	"net"
	"net/rpc"
)

type UserService struct {

}

func(this *UserService) GetUserName(userid int, username *string) error  {
	if userid == 101 {
		*username = "vip"
	} else {
		*username = "guest"
	}
	return nil
}

func main() {
	lis, _ := net.Listen("tcp", ":8082")
	rpc.Register(new(UserService))

	for {
		client, _ :=lis.Accept()
		rpc.ServeConn(client)
	}
}
  • 文件 /Users/go/src/com.net/myclient/main.go
package main

import (
	"fmt"
	"net/rpc"
)

func main() {
	client, _ := rpc.Dial("tcp","127.0.0.1:8082")
	username := ""
	err:=client.Call("UserService.GetUserName", 102, &username)
	if err != nil{
		fmt.Println(err)
		return
	}
	fmt.Println(username)
}

12.2 JSONRPC 使用、使用 PHP 调用;

  • 上一节,只适合 go 与 go 之间的调用(因为它数据编码使用了 go 的 gob 编码格式)
  • 要想让异构系统调用,就需要使用一些通用的编码格式,譬如 JSON

使用 PHP 写个代码连接 socket

<?php
$fp = stream_socket_client("tcp://127.0.0.1:8082",$errno, $errstr, 3);	//连接 go 的rpc server,其实就是socket连接
if (!$fp) {
    echo "$errstr ($errno)<br />\n";
    return;
}
 fwrite($fp, json_encode([
        'method' =>"UserService.GetUserName",
        'params' =>[102],
        'id'     => 0,
    ])."\n");

    echo fgets($fp);

fclose($fp);
  • 文件 /Users/go/src/com.net/myrpcserver/main.go
package main

import (
	"net"
	"net/rpc"
	"net/jsonrpc"
)

type UserService struct {

}

func(this *UserService) GetUserName(userid int, username *string) error  {
	if userid == 101 {
		*username = "vip"
	} else {
		*username = "guest"
	}
	return nil
}

func main() {
	lis, _ := net.Listen("tcp", ":8082")
	rpc.Register(new(UserService))

	for {
		client, _ :=lis.Accept()
		jsonrpc.ServeConn(client)	// 使用 jsonrpc 调用
	}
}
  • 文件 /Users/go/src/com.net/myclient/main.go
package main

import (
	"fmt"
	"net/rpc"
	"net/jsonrpc"
)

func main() {
	client, _ := jsonrpc.Dial("tcp","127.0.0.1:8082")
	username := ""
	err:=client.Call("UserService.GetUserName", 102, &username)
	if err != nil{
		fmt.Println(err)
		return
	}
	fmt.Println(username)
}

12.3 初步使用 Protobuf 定义自己的 RPC 服务数据;

Protobuf:Google Protocol Buffer

  • 轻便高效的序列化数据结构的协议,可以用于网络通信和数据存储。
  • 特点:性能高、传输快、维护方便,一些第三方 rpc 库都会支持 protobuf
  • github地址:https://github.com/protocolbuffers/protobuf
  • golang库所属地址:https://github.com/golang/protobuf

12.4 gRPC,创建服务端和客户端;

13 Context 上下包;

14 包依赖管理和系统部署;

14.1 go.mod文件;

当项目下有 go,mod 文件时,则会使用 go modules 机制

  • 首先创建一个空文件夹,路径不能有中文、空格和特殊字符
  • cd 进入,执行 go mod init mytest(mytest为模块名)
  • 此时会在文件夹中创建一个 go.mod 文件,里面第一行就是 module mytest
  • 文件 /Users/go/gopro/go.mod
module mytest

简单使用

  • 文件 /Users/go/gopro/mycore/functions.go
package mycore

import "fmt"

func ShowName() {
	fmt.Println("huahua")
}
  • 文件 /Users/go/gopro/main.go
package main

import "mytest/mycore"

func main() {
	//fmt.Println("hello moto")

	mycore.ShowName()
}

14.2 包任意位置的引用方式;

/mycore/functions.go 移动到项目外面

// 在 go.mod 中加入
require (
    mycore v0.0.0
)

replace (
    mycore v0.0.0 => ../mycore
)

// mycore 下新建 go.mod
cd ~/go/mycore 
go mod init mycore
  • 文件 /Users/go/gopro/main.go
package main

import "mycore"

func main() {
	mycore.ShowName()
}

14.3 引入第三方包(sql-driver为例);

  • 之前使用过:https://github.com/go-sql-driver/mysql
  • 现在是用新的方式引用
// cd 进入项目目录
// 解决: invalid version: Get "https://proxy.golang.org/github.com/go-sql-driver/mysql/@v/master.info": dial tcp 142.251.42.241:443: i/o timeout
go env -w GOPROXY=https://goproxy.cn
go get -u github.com/go-sql-driver/mysql@master	// 如果指定版本,则”@x.xx“

// go.mod 自动写入
module mytest

require (
	github.com/go-sql-driver/mysql v1.6.1-0.20220413072545-ad9fa14acdcf // indirect,此项自动导入
	mycore v0.0.0
)

replace mycore v0.0.0 => ../mycore

14.4 docker 中部署go环境、module方式引用第三方包、运行和测试;

下载镜像:https://hub.docker.com/_/golang

docker pull golang:1.18.1-alpine3.15

# https://github.com/docker-library/golang/blob/75f3d2fdbad4799dbfc8f962480a4984f8fcdaee/1.18/alpine3.15/Dockerfile
# 根据 dockerfile,目录在 /go

# 进入本机 go 目录
cd ~/go
mkdir mygo
cd mygo
vim main.go

# 写入
package main

import "fmt"
func main(){
  fmt.Println("test go in docker")
}

# 利用容易编译
# 进入 docker:交互方式启动,一旦停止就删掉
docker run -it --rm \
-v /Users/hualaoshuan/go/mygo:/mygo \
-w /mygo \
golang:1.18.1-alpine3.15 \
go build

# 运行
./mygo

使用第三方包

# 第1步:
# 我们把/go 映射出来。方便下次运行时 再挂载进去
# 创建一个文件夹叫做 gopath (/Users/hualaoshuan/gopath)
cd ~/go
mkdir gopath

# 第2步:
# 手动创建 go.mod 文件夹
cd mygo
# 写入 module mygo
vi go.mod

# 第3步:
# 下载 git 并安装,先创建临时容器进入
docker run --name installgit -it golang:1.18.1-alpine3.15 sh 

apk --no-cache add git openssh && \
rm -rf /var/lib/apt/lists/* && \
rm /var/cache/apk/*

# 退出容器后,执行
docket start installgit
docker commit installgit golang:1.18.1-alpine3.15

# 下载依赖
docker run -it --rm \
-v /Users/hualaoshuan/go/mygo:/mygo \
-v /Users/hualaoshuan/go/gopath:/go \
-w /mygo \
golang:1.18.1-alpine3.15  \
go get github.com/pquerna/ffjson

# 修改代码
package main

import (
  "github.com/pquerna/ffjson/ffjson"
  "fmt"
)

type NewsModel struct {
  NewsID int
  NewsTitle string
}

func (news NewsModel) ToJSON() string {
  result,err:=ffjson.Marshal(news)
  if err!=nil {
    return err.Error()
  } else {
   return string(result)
  }
}

func main()  {
  news:=NewsModel{123,"title"}
  fmt.Println(news.ToJSON())
}

# 再次编译执行
docker run -it --rm \
-v /Users/hualaoshuan/go/mygo:/mygo \
-v /Users/hualaoshuan/go/gopath:/go \
-w /mygo \
golang:1.18.1-alpine3.15  \
go build

14.5 在 docker 中使用 module 方式安装gin框架、运行测试网站;

一些准备

# 进入容器
docker run -it --rm \
-v /Users/hualaoshuan/go/mygo:/mygo \
-v /Users/hualaoshuan/go/gopath:/go \
-w /mygo \
golang:1.18.1-alpine3.15  \
sh

# 生成
go mod init mygo
# 找回依赖包,并且在 go.mod 下配置
go mod tidy
# 返回
go: finding module for package github.com/pquerna/ffjson/ffjson
go: downloading github.com/pquerna/ffjson v0.0.0-20190930134022-aa0246cd15f7
go: found github.com/pquerna/ffjson/ffjson in github.com/pquerna/ffjson v0.0.0-20190930134022-aa0246cd15f7

Gin:https://github.com/gin-gonic/gin

# 查看 CGO_ENABLED="1"
go env

# 使用纯 go 编译
CGO_ENABLED=0 go  get -v github.com/gin-gonic/gin

  • 文件 /Users/go/mygo/main.go
package main

import "github.com/gin-gonic/gin"
func main(){
  r := gin.Default() 
  r.GET("/", func(c *gin.Context) { 
     c.JSON(200, gin.H{ "message": "hello gin", })
 })
 r.Run() // 开启服务,默认端口是8080
}

运行

docker run  -d --name mygin --rm \
-p 8080:8080 \
-e CGO_ENABLED=0 \
-v /Users/hualaoshuan/go/mygo:/mygo \
-v /Users/hualaoshuan/go/gopath:/go \
-w /mygo \
golang:1.18.1-alpine3.15  \
go run main.go

curl localhost:8080
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值