跳至主要內容

Go

LiCheng大约 5 分钟

Go

介绍

  • 2019年开始了解Go语言,到现在慢慢补。
  • 本文档介绍了Go语言基础

描述

官网

安装提示

下载完后打开运行-> Next -> 按默认安装程序走就行了。

语法糖

方法返回值赋值

func TestOk(t *testing.T) {
	a, err := A()
	fmt.Println(a)
	fmt.Println(err.Error())
}
// A 这里先定义返回变量值的名字,后面可以通过return来进行直接返回
func A() (a int, err error) {
	a = 1
	err = errors.New("错误")
	return
}

go基础部分

变量赋值

func main() {
	var a = "Hello"   //可以被修改,匿名类型,用于定义默认的值
	const b = "World" //无法被修改
	a = "Ok"
	fmt.Println(a + b)

	//申明类型,用于接受确定的类型,定义全局变量使用
	var sum int //定义变量
	fmt.Println(sum)
	var list []string //定义数组
	fmt.Println(list)
	var hashMap map[string]string //定义map
	fmt.Println(hashMap)
}

流程语句

  • 语法控制
func main() {
	var list = []string{"Hello", "World"}
	for i := 0; i < 3; i++ { //普通for循环
		fmt.Printf("打印:%v\n", i)
	}
	for i, item := range list { //for增强
		fmt.Printf("下标:%v,属性:%v\n", i, item)
	}
	if true {
		fmt.Println("真")
	}
	var count = 3
	for count > 0 { //死循环 => for true {}
		fmt.Println("死循环")
		time.Sleep(1 * time.Second)
		count--
	}
}

Map和List

func main() {
	//map
	hashMap := make(map[string]string, 0)
	hashMap["A"] = "HelloWorld" //插入
	fmt.Println(hashMap["A"])   //获取
	delete(hashMap, "A")        //删除
	fmt.Println(hashMap)

	//list
	list := make([]string, 0)
	list = append(list, "Hello", "World")
	fmt.Println(list[0])                 //获取
	fmt.Println(list[1:])                //截取
	list = append(list[:1], list[2:]...) //删除
	fmt.Println(list)
	var i = 1
	list = append(list[0:i], list[i-1:]...) //插入元素
	list[0] = "Ok"
	fmt.Println(list)
}

异常处理

func Test1(t *testing.T) {
 defer func() {
  if r := recover();r!=nil{
			log.Printf("%v",r)
		}
	}()

 panic("异常示例1")
}

自定义错误类型

type ServiceError struct {
	msg string
}

func IsServiceError(a any) bool {
	switch a.(type) {
	case *ServiceError:
		return true
	case ServiceError:
		return true
	}
	return false
}

func NewServiceError(msg string) *ServiceError {
	return &ServiceError{msg: msg}
}

func (s ServiceError) Error() string {
	return s.msg
}

func (s ServiceError) RuntimeError() {
	panic(s.msg)
}
  • 测试
func main() {
	defer func() {
		if r := recover(); r != nil {
			log.Println(config.IsServiceError(r)) //false
			log.Println(r)
		}
	}()
	//panic(config.NewServiceError("自定义错误!")) //这个使用,并注释下面一行,则为true
	panic("自定义错误!") 
}

闭包

func Print() func(a int) int { //闭包函数,返回值必须一致
	i := 1
	return func(a int) int {
		fmt.Println(i) //内部使用外部!
		return a
	}
}

接口与结构体

// UserService 接口在go变量想要被外部访问,则需要首字母大写
type UserService interface {  
	Add(str string)string
	Print()
}

// UserServiceImpl 结构体
type UserServiceImpl struct {
	Title   string  
	Name    string
} 
func (UserServiceImpl) Add(str string)string  {
	return str
}
func (UserServiceImpl)  Print()  {
	fmt.Println("HelloWorld")
}

// var book = UserServiceImpl{"a","b"}  //创建对象

指针概念

  • 带&号则代表传递指针,在其方法里面执行的修改可以影响其原变量。否则则不影响!
// 查看列表 ok
func userList(c *gin.Context) {
	var where entity.User
	
	err := c.Bind(&where) 
	if err != nil {
		fmt.Println(err)
	}
	fmt.Println(where)
	var users []entity.User
	config.Db.Where(&where).Find(&users)

	c.JSON(http.StatusOK, util.OkData(users))
}

多线程通道

  • 模拟多线程执行任务进行结果返回!
func main() {
	a := make(chan int)
	b := make(chan int)

	go func() {
		time.Sleep(3 * time.Second)
		a <- 1011
	}()

	go func() {
		time.Sleep(2 * time.Second)
		b <- 1111
	}()

	// 使用 <-b , <-a 阻塞来获取返回数据,多线程处理任务时使用
	log.Println(<-b)
	log.Println(<-a)

}

Go实践

  • 方法执行必须返回副本,而不能返回指针。否则list类型无法遍历。

开源库

高级部分

  • 以下都是基础阶段用不到的内容

镜像配置

微服务

多模块开发

  • 在根目录下初始化 go work 会创建一个 go.work 文件
  • go work init
  • 创建 user 目录并进入,执行以下命令创建 go 模块
  • go mod init user
  • 在根目录的work文件引入
use (
	core
	user
)

context上下文

  • 上下文
var contextData = context.Background()
const Key = "Key"


// SetContext 设置上下文数据,这里传入的类型要与取出来的类型一致
func SetContext(v int64) {
	contextData = context.WithValue(contextData, Key, v)
}

// GetContext 获取上下文数据
func GetContext() int64 {
	value := contextData.Value(Key)
	if value == nil {
	panic("没有数据")
	}
	return value.(int64)
}

互斥锁

// 互斥锁 , 每个对象都对应于一个可称为" 互斥锁" 的标记,这个标记用来保证在任一时刻,只能有一个线程访问该对象。
var lock sync.Mutex

//var lock sync.RWMutex

var v = 0

func main() {
	for i := 0; i < 10; i++ {
		go sum()
	}
	//fmt.Println(<-str)
	time.Sleep(5 * time.Second)
	fmt.Println(v)
}

func sum() {
	for i := 0; i < 10000; i++ {
		lock.Lock()
		v++
		lock.Unlock()
	}
}

单元测试

  • sort_test.go
  • 以_test结尾的go文件就是测试
  • 测试分为三个步骤
  • 1: 输入测试数据
  • 2: 执行测试的功能
  • 3: 验证测试的功能

工具类

Jwt

  • go get -u github.com/golang-jwt/jwt/v4
package util
import (
	"fmt"
	"github.com/golang-jwt/jwt/v4"
	"time"
)
const key = "izVguZPRsBQ5Rqw6dhMvcIwy8_9lQnrO3vpxGwPxfAxDs"
const UserIdKey = "userId"
const expireTimeKey = "expireTime"
func GetToken(id interface{}) string {
	mySigningKey := []byte(key)
	claims := &jwt.MapClaims{
		UserIdKey:     id,
		expireTimeKey: time.Now(),
	}
	token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
	t, err := token.SignedString(mySigningKey)
	if err != nil {
		panic(err)
	}
	return t
}
// GetUserId  获取token解析,请使用 GetTokenParse 替代
// Deprecated
func GetUserId(t string) string {
	return GetTokenParse(t)
}
// GetTokenParse 获取token解析
func GetTokenParse(t string) string {
	token, err := jwt.Parse(t, func(token *jwt.Token) (interface{}, error) {
		return []byte(key), nil
	})
	//log.Println(token.Header)
	//log.Println(token.Claims)
	if err != nil {
		panic(err)
	}
	id := (token.Claims.(jwt.MapClaims))["userId"]
	return fmt.Sprintf("%v", id)
}

打包

set GOOS=linux
set GOARCH=amd64
go build -ldflags "-w -s"  -o ./main main.go