新建一个项目,如果想把它交给GoModules管理,需要在项目目录下运行命令行并输入:
go mod init
go语言依赖管理:go.mod文件,go mod相关命令。
golang自动下载所有依赖(包括goland怎么设置)
golang自动下载所有依赖最好用的一个命令
go get -d -v ./… (下载全部依赖,经测试好用。)
1、拉取别人开发的项目到本地如何跑:
重要:为什么找不到依赖?
解决:命令行中:
go mod init 项目名//生成go.mod文件
go mod tidy//下载全部依赖的命令
go run main.go//运行main.go之前也会下载全部依赖
如果还是下载不了,检查代理是否配置好:
GOPROXY=https://goproxy.cn,direct
另外,如果go.mod还有飘红,但文件夹里有,可以不用理了,可能是系统或IDE问题。
2、自己新建一个项目,包如何管理
gopath已经过时了,现在都用go module + git的形式管理包。
步骤:
1、在github或gitee上新建仓库,初始化一个readme.md
2、把项目拉取到本地。
3、新建两个文件夹,注意规则:每个文件夹内只允许有一个package。
4、两个文件夹内分别新建文件,其中一个为main.go,调用另一个包的文件。
5、go mod init 项目名
项目名和git路径对应上
如 git@gitee.com:sealseadog/my-block-chain01.git
项目名为:gitee.com/sealseadog/my-block-chain01
6、导包时,import “项目名/包名”
如:import “gitee.com/sealseadog/my-block-chain01/chain”
0、builtin
go语言的关键字只有25个:
package import
var const type struct func interface map
go chan
if else for range break return continue
select switch case fallthrough default
defer
goto
除关键字之外,不导包就直接能用的方法和类型是预定义标识符。
这些标识符在builtin包中。如:
int float32 bool string
byte//可存字符
rune//存更大的字符
true false iota//定义枚举常量
new() make()//区别是什么?
close() cap() len() append() copy() print() delete()//见名知意
panic() recover()
1、time
time.Sleep(1 * time.Second)//延时等待1秒
//如果不是1,而是一个变量或常量,则需要类型转换time.Duaration()
time.Sleep(time.Second * time.Duaration(testTime))
ping := time.Now().Sub(pingStart)//计算与pingStart的差值
2、strings
strings.Repeat(str,3)//将str字符串重复3遍
var strs []string = []string{"hello", "world", "haha"}
join := strings.Join(strs, ";")
//将字符串切片组成一个字符串,以";"隔开
fmt.Println(join)
3、encoding/json
package main//golang study中的demo:
import (
"encoding/json"
"fmt"
)
type Movie struct {
Title string `json:"title"`
Year int `json:"year"`
Price int `json:"rmb"`
Actors []string `json:"actors"`
}
func main() {
movie := Movie{"喜剧之王", 2000, 10, []string{"xingye", "zhangbozhi"}}
//编码的过程 结构体---> json
jsonStr, err := json.Marshal(movie)
if err != nil {
fmt.Println("json marshal error", err)
return
}
fmt.Printf("jsonStr = %s\n", jsonStr)
//解码的过程 jsonstr ---> 结构体
//jsonStr = {"title":"喜剧之王","year":2000,"rmb":10,"actors":["xingye","zhangbozhi"]}
myMovie := Movie{}
err = json.Unmarshal(jsonStr, &myMovie)
if err != nil {
fmt.Println("json unmarshal error ", err)
return
}
fmt.Printf("%v\n", myMovie)
}
Lotus代码中的示例:
//把自定义结构体转换成json:注意字段首字母应大写才可访问到。
b, err := json.MarshalIndent(&stores.LocalStorageMeta{
ID: stores.ID(uuid.New().String()),
Weight: 10,
CanSeal: true,
CanStore: true,
}, "", " ")
//把json字符串转换成结构体对象
err := json.Unmarshal(b, &psm)
4、reflect
package main
import (
"fmt"
"reflect"
)
//主要用两个方法:TypeOf()得到对象的类型,ValueOf()得到对象的值。
func reflectNum(arg interface{}) {
fmt.Println("type : ", reflect.TypeOf(arg))
fmt.Println("value : ", reflect.ValueOf(arg))
}
func main() {
var num float64 = 1.2345
var num2 int64 = 51
reflectNum(num)
reflectNum(num2)
}
5、net和net/http
http包包含http客户端和服务端的实现,利用Get,Head,Post,以及PostForm实现HTTP或者HTTPS的请求.
当客户端使用完response body后必须使用close对其进行关闭.如下所示
resp, err := http.Get("http://example.com/")
if err != nil {
// handle error
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
// ...
6、os,io和io/ioutil,path和path/filepath
os库包含了常用的系统级别调用的操作。
io库定义了读和写等方法。
package main
import (
"fmt"
"io"
"os"
)
func main() {//golangStudy示范os.OpenFile()和io.Writer的用法
//tty: pair<type:*os.File, value:"/dev/tty"文件描述符>
tty, err := os.OpenFile("D:/lee/show.txt", os.O_RDWR, 0)
if err != nil {// ↑↑↑从该路径读取文件
fmt.Println("open file error", err)
return
}
//r: pair<type: , value:>
var r io.Reader
//r: pair<type:*os.File, value:"/dev/tty"文件描述符>
r = tty
//w: pair<type: , value:>
var w io.Writer
//w: pair<type:*os.File, value:"/dev/tty"文件描述符>
w = r.(io.Writer)//↓↓↓向该txt文件写入内容
w.Write([]byte("HELLO THIS is A TEST!!!\n"))
}
os包从环境中读取配置
os.Getenv("LOTUS_DEV")
os包设置环境变量
err := os.Setenv("BELLMAN_NO_GPU", "true")
7、context
7.1 context简单理解:
主要用于在协程之间传递上下文信息,如:
1、取消信号
2、超时信号
3、截止时间信号
4、传递key-value值
7.2 最简单的应用:传递key-value值
package main
import (
"context"
"fmt"
"time"
)
func g2(ctx context.Context) {
fmt.Println(ctx.Value("third"))
fmt.Println("第四、周期永远在。")
}
func g(ctx context.Context) {
fmt.Println(ctx.Value("first"))
fmt.Println("第二,分析周期")
go g2(context.WithValue(ctx, "third", "第三,应对周期有三个要点"))
}
func main() {
ctx := context.WithValue(context.Background(), "first", "第一,认识周期,")
go g(ctx)
time.Sleep(time.Second)
}
7.3、取消信号
取消信号传递过来之后,还得自己去解决,进行取消操作才能退出协程。
package main//简单示例
import (
"context"
"log"
"time"
)
func main() {
ctx, cancel := context.WithCancel(context.Background())
//返回值cancel是个函数,可以用来结束goroutine
go g1(ctx)
for i := 0; i < 10; i++ {
log.Println("count = ", i)
if i >= 3 {
cancel() //取消
}
time.Sleep(time.Second)
}
}
func g1(ctx context.Context) {
select {
case <-ctx.Done():
log.Println("g1取消了")
return
}
}
package main//展示goroutine无限套娃情况下的cancel()
import (
"context"
"log"
"time"
)
func main() {
ctx, cancel := context.WithCancel(context.Background())
go g1(ctx)
for i := 0; i < 10; i++ {
log.Println("count = ", i)
if i >= 3 {
cancel() //取消
}
time.Sleep(time.Second)
}
}
func g1(ctx context.Context) {
go g2(ctx)//调用,套娃
select {
case <-ctx.Done():
log.Println("g1取消了")
return
}
}
func g2(ctx context.Context) {
select {
case <-ctx.Done():
log.Println("g2取消了")
return
}
}
7.4、取消和超时信号同时使用
package main
import (
"context"
"log"
"time"
)
const testTime int = 6 //测试超时的情况
//const testTime int = 3 //测试手动取消的情况
func main() {
ctx, cancel := context.WithTimeout(context.Background(), time.Second*5)
go g1(ctx)
for i := 0; i < 10; i++ {
log.Println("count = ", i)
if i >= testTime {
log.Println("手动取消")
cancel() //取消
}
time.Sleep(time.Second)
}
}
func g1(ctx context.Context) {
done := make(chan struct{}, 1) //写1防止内存泄漏
go func() {
time.Sleep(time.Second * time.Duration(testTime))
done <- struct{}{}
}()
select {
case <-ctx.Done():
log.Println("g1被取消或超时了")
return
case <-done: //正常执行完成
log.Println("g1正常执行完成")
return
}
}
8、runtime
尽管 Go 编译器产生的是本地可执行代码,这些代码仍旧运行在 Go 的 runtime(这部分的代码可以在 runtime 包中找到)当中。这个 runtime 类似 Java 和 .NET 语言所用到的虚拟机,它负责管理包括内存分配、垃圾回收、栈处理、goroutine、channel、切片(slice)、map 和反射(reflection)等等。
9、sync
自旋锁和互斥锁的区别
详解go中的混合锁 - mutex
type fundedAddress struct {
//...
lk sync.RWMutex
//...
}
func (a *fundedAddress) getReserved() abi.TokenAmount {
a.lk.RLock()//禁止写入,不禁止读取对应Lock()是禁止读写。
defer a.lk.RUnlock()//释放锁
return a.state.AmtReserved
}
三、go持久层框架gorm
简介:gorm是中国的golang开发者jinzhu开发的持久层框架,目前最新版本是v2版。
v1版的依赖:
"github.com/jinzhu/gorm"
_ "github.com/jinzhu/gorm/dialects/mysql"
v2版的依赖:
"gorm.io/driver/mysql"
"gorm.io/gorm"
四、Web框架Gin