import (_ "GolangStudy/lib1" //匿名导包,这样不适用这个包也不会报错mylib1 "GolangStudy/lib1" //别名导包,可以直接用mylib1. "GolangStudy/lib1" //直接把这个包导入本地包。比如调用xx()函数就不用lib1.xx()了,可以直接写xx()
)
func main(){defer fmt.Println("main1 end.")defer fmt.Println("main2 end.")fmt.Println("1 end.")fmt.Println("2 end.")
}
//执行结果
1 end.
2 end.
main2 end.
main1 end.
//固定长度数组
var myArray [10]int
myArray := [10]int{1,2,3,4} //golang中没有初始化的值默认为0
fmt.Printf("type: %T", myArray) //输出为:types: [10]int go中定长数组的长度也是类型中的一部分
func printArray(myArray [10]int){} //这个函数就只能接收长度为10的数组,不能接收其他长度的数组
func printArray(myArray []int){} //这个函数不能接收myArray,因为定长数组和切片是不同类型func printArray(myArray [10]int){myArray[1] = 24 //这条语句不会影响传进来的原数组的值
}
//切片
mySlice := []int{1,2,3} //声明并初始化一个长度为3的切片
var mySlice []int //声明一个切片,但是并未分配空间
fmt.Printf("type: %T", mySlice) //输出为:types: []int
var mySlice []int
mySlice[0] = 1 //由于前面slice并未被分配空间,因此直接访问下标会出现越界错误
mySlice = make([]int, 3) //这样就分配了长度为3的空间,默认值为0
var mySlice2 = make([]int, 3) //切片的另一种定义方式
var mySlice = make([]int, 3, 5) //定义一个长度为3,容量为5的切片
mySlice = append(mySlice, 1) //向切片中追加一个元素1,此时长度为4,容量为5
fmt.Printf("len=%d, cap=%d", len(mySlice), cap(mySlice)) //输出 len=4, cap=5
mySlice = append(mySlice, 1) //向切片中追加一个元素1,此时长度为5,容量为5mySlice = append(mySlice, 1) //向切片中追加一个元素1,此时长度为6,容量为10s1 := mySlice[0:2] //截取前两个元素,左闭右开,引用传递
var myMap map[string]string //声明map,并未实际分配空间
myMap = make(map[string]string, 10) //分配空间,空间长度可省略

this有两种,一种是this指针,指向当前对象,第二种是this对象,是当前对象的一个拷贝
方法名或成员名大写,表示其他包可以访问,否则只能在本包访问
type Test struct{a intb string
}
func (this Test) SetA(c int){this.a = c //这时候这个类对象中的a并不会被更改,因为this只是一个对象的拷贝
}
func (this *Test) SetA(c int){this.a = c //这时这个类对象中的a会被修改为c,因为this是这个对象的指针
}
type Human struct{name stringsex string
}
func (this *Human) Eat(){//...
}
type SuperMan struct{Human //SuperMan类继承了Human类的方法level int
}
//重定义父类的方法Eat()
func (this *SuperMan) Eat(){fmt.Println("SuperMan.Eat...")
}
package main//接口,本质上是一个指针
type AnimalIf interface {Sleep()GetColor() stringGetType() string
}//具体的类
type Cat struct {color string
}
func (this *Cat) Sleep() {fmt.Println("Cat is Sleep")
}
func (this *Cat) GetColor() string {return this.color
}
func (this *Cat) GetType() string {return "Cat"
}
func main() {var animal AnimalIFanimal = &Cat{"Green"}
}
package mainimport "fmt"func myFunc(arg interface{}) {fmt.Println(("a ...interface{}"))value, ok := arg.(string)if !ok {fmt.Println("arg is not string type")} else {fmt.Println("arg is string type, value = ", value)}
}
type Book struct {auth string
}
func main() {book := Book{"Golang"}myFunc(book)myFunc(100)myFunc("abc")myFunc(3.14)
}
变量内置了一个pair结构,用于存储数据类型和值
变量的结构
变量在赋值时,会同时把自己的pair结构赋值过来
package mainfunc main(){var a string//paira = "aceld"//pairvra allType interface{}allType = a
}
通过reflect包提供的函数获取变量的类型和值
reflect包
func Valueof(i interface{}) Value {...}
func Typeof(i interface{}) Type {...}
package mainimport ("fmt""reflect"
)type User struct {Id intName stringAge int
}func (this *User) Call() {fmt.Println("user is called ..")
}func main() {user := User{1, "Aceld", 18}DoFiledAndMethod(user)
}func DoFiledAndMethod(input interface{}) {inputType := reflect.TypeOf(input)fmt.Println("inputType is :", inputType.Name())inputValue := reflect.ValueOf(input)fmt.Println("inputValue is : ", inputValue)//通过type获取里面的字段//1. 获取interface的reflect.Type,通过Type得到NumField,进行遍历//2. 得到每个field,数据类型//3. 通过field的Interface()方法得到对应的valuefor i := 0; i < inputType.NumField(); i++ {field := inputType.Field(i)value := inputValue.Field(i).Interface()fmt.Printf("%s: %v = %v\n", field.Name, field.Type, value)}for i := 0; i < inputType.NumMethod(); i++ {m := inputType.Method(i)fmt.Printf("%s: %v\n", m.Name, m.Type)}
}
package mainimport ("encoding/json""fmt""reflect"
)
type Movie struct {Title string `json:"title"`Year int `json:"year"`Price int `json:"rmb"`Actors []string `json:"actors"`
}type resume struct {Name string `info:"name" doc:"我的名字"`Sex string `info:"sex"`
}func findTag(str interface{}) {t := reflect.TypeOf(str).Elem()for i := 0; i < t.NumField(); i++ {taginfo := t.Field(i).Tag.Get("info")tagdoc := t.Field(i).Tag.Get("doc")fmt.Println("info: ", taginfo, " doc:", tagdoc)}
}
func main() {var re resumefindTag(&re)movie := Movie{"喜剧之王", 2000, 10, []string{"xingye", "zhangbozhi"}}//编码:将结构体编码为json的过程jsonStr, err := json.Marshal(movie)if err != nil {fmt.Println("json marshal error ", err)return}//解码:将json解码为结构体myMovie := Movie{}err = json.Unmarshal(jsonStr, &myMovie)if err != nil {fmt.Println("json unmarshal error ", err)return}fmt.Printf("jsonStr = %s\n", jsonStr)fmt.Printf("%v\n", myMovie)
}

老版的调度器
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-j9DFs6ft-1669013131369)(C:\Users\12610\AppData\Roaming\Typora\typora-user-images\image-20221121101734855.png)]](/uploadfile/202402/81b4a225a288af.png)
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jBZVRq2K-1669013131370)(C:\Users\12610\AppData\Roaming\Typora\typora-user-images\image-20221121101415323.png)]](/uploadfile/202402/cbfb2c95b71d4ef.png)
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-poDIFqGA-1669013131371)(C:\Users\12610\AppData\Roaming\Typora\typora-user-images\image-20221121101650404.png)]](/uploadfile/202402/d30df7be36d7f3a.png)
复用线程
work stealing机制(工作窃取):当本地队列为空,可以从其他队列(其他本地队列或全局队列)窃取任务到本地队列中
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-y7qU4F9u-1669013131372)(C:\Users\12610\AppData\Roaming\Typora\typora-user-images\image-20221121102659710.png)]](/uploadfile/202402/2b25175cbac33f1.png)
hand-off机制:当正在执行的G1发生阻塞时,整个线程会被阻塞住。此时,再启动一个内核级线程,将当前本地队列挂到新的内核线程上,当前的G1继续在本地阻塞,执行完如果还要执行就加入其他队列中,否则销毁。
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-F3vuRRwL-1669013131373)(C:\Users\12610\AppData\Roaming\Typora\typora-user-images\image-20221121103038447.png)]](/uploadfile/202402/780ba35c9e73a75.png)
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-aRGJB9Mt-1669013131377)(C:\Users\12610\AppData\Roaming\Typora\typora-user-images\image-20221121103110453.png)]](/uploadfile/202402/7538a1705ae4fd3.png)
利用并行:通过GOMAXPROCS限定P的个数=CPU核数/2
抢占:一个G最多10ms,时间片结束另一个G可以抢占
全局G队列:
go func(){...}
runtime.Goexit() //该函数用于退出当前goroutine
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Ko9cqvNZ-1669013131379)(C:\Users\12610\AppData\Roaming\Typora\typora-user-images\image-20221121113341791.png)]](/uploadfile/202402/6a3457589c148f1.png)
package mainimport "fmt"func main() {//定义一个无缓冲channelc := make(chan int)go func() {for {defer fmt.Println("goroutine结束")fmt.Println("goroutine正在运行...")//由于是无缓冲channel,所以当c中数据未被消费时,此处会阻塞等待,直到channel为空再放入c <- 666 //将666 发送给c}}()i := 0for {i++}num := <-c //从c中接收数据,并赋值给num。等待是阻塞过程。fmt.Printf("receive num from channel c: %d\n", num)fmt.Println("main go routine 结束...")
}
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Hrauu5w3-1669013131380)(C:\Users\12610\AppData\Roaming\Typora\typora-user-images\image-20221121113748162.png)]](/uploadfile/202402/11d6adf97aa9b.png)
package mainimport ("fmt""time"
)func main() {//定义一个有缓冲channelc := make(chan int, 3)fmt.Println("len(c) = ", len(c), ", cap(c)", cap(c))go func() {defer fmt.Println("goroutine结束")for i := 0; i < 3; i++ {c <- ifmt.Println("子go程正在运行,发送的元素=", i, " len(c)=", len(c), ", cap(c)=", cap(c))}}()time.Sleep(2 * time.Second)for i := 0; i < 3; i++ {num := <-c //从c中接收数据fmt.Println("num=", num)}fmt.Println("main go routine 结束...")
}
c := make(char int)
close(c) //关闭一个channel
if data, ok := <-c; ok {...} //判断channel是否为打开状态,若ok为true表示没有关闭(注意这个不是判断是否为空,而是是否打开)
for data := range c {...}
package mainimport "fmt"func fibonacii(c, quit chan int) {x, y := 1, 1for {select {//如果c可写case c <- x:tmp := yy = x + yx = tmpcase <-quit: //如果quit可读fmt.Println("quit")return}}
}
func main() {c := make(chan int)quit := make(chan int)go func() {for i := 0; i < 6; i++ {fmt.Println(<-c)}quit <- 0}()fibonacii(c, quit) //channel是引用传递
}
目录结构
弊端
没有版本控制概念
go get -u github.com/xxx //不能拉取指定版本,只拉取最新
无法同步一致第三方版本号:不同的go项目,引用的相同库的版本无法一致
无法指定当前项目引用的库版本号
建议为了和GOPATH分开,不要将源码创建在GOPATH/src下
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ngnsGGbH-1669013131383)(C:\Users\12610\AppData\Roaming\Typora\typora-user-images\image-20221121135209619.png)]](/uploadfile/202402/1e5464374682f8a.png)
GO111MODULE:该环境变量为Go modules的开关
go env -w GO111MODULE=on
GOPROXY:该环境变量用于设置Go模块代理,其作用是用于使Go在后续拉取模块版本时直接通过镜像站点来快速获取(以前是手动下载,现在自动到GOPROXY下载)
GOPROXY="https//goproxy.cn,direct" #这个direct表示默认去该网址拉取,如果该网址找不到则去包指定网址拉取
import "githubs.com/xxx.json" #比如这个会先去GOPROXY拉取,否则去github上拉
GOSUMDB:它的值是一个Go checksum database,用于在拉取模块版本时保证拉取到的模块版本数据未经过篡改,若发现不一致,也就是可能存在篡改,将会立即中止。你在本地对依赖进行变动(更新/添加)操作时,Go 会自动去这个服务器进行数据校验,保证你下的这个代码库和世界上其他人下的代码库是一样的。和go.mod一样,Go 会帮我们维护一个名为go.sum的文件,它包含了对依赖包进行计算得到的校验值。如果你的代码仓库或者模块是私有的,那么它的校验值不应该出现在互联网的公有数据库里面,但是我们本地编译的时候默认所有的依赖下载都会去尝试做校验,这样不仅会校验失败,更会泄漏一些私有仓库的路径等信息,我们可以使用GONOSUMDB这个环境变量来设置不做校验的代码仓库, 它可以设置多个匹配路径,用逗号相隔。举例:
GONOSUMDB=*.corp.example.com,rsc.io/private
GOPRIVATE:go 命令会从公共镜像 http://goproxy.io 上下载依赖包,并且会对下载的软件包和代码库进行安全校验,当你的代码库是公开的时候,这些功能都没什么问题。但是如果你的仓库是私有的怎么办呢?
环境变量 GOPRIVATE 用来控制 go 命令把哪些仓库看做是私有的仓库,这样的话,这些库会从私有仓库地址去拉取,并且跳过 proxy server 和校验检查(设置了GOPRIVATE之后,可以不用再设置GONOSUMDB和GONOPROXY),这个变量的值支持用逗号分隔,可以填写多个值,例如:
GOPRIVATE=*.corp.example.com,rsc.io/private
这样 go 命令会把所有包含这个后缀的软件包,包括 http://git.corp.example.com/xyzzy , http://rsc.io/private, 和 http://rsc.io/private/quux 都以私有仓库来对待。
go env -w GO111MODULE=on
或者
export GO111MODULE=on
mkdir module_test
cd module_test#初始化Go Modules,自动创建go.mod
go mod init github.com/aceld/modules_test #后面指定模块名称,别人就可以通过这一串来import这个模块#创建main.go文件,写代码,导入一些包
go get xxx #下载导入的包,默认下载到$GOPATH/pkg/mod下
#也可以自动下载
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fUzowbMe-1669013131384)(C:\Users\12610\AppData\Roaming\Typora\typora-user-images\image-20221121143659656.png)]](/uploadfile/202402/2088702eb17b849.png)
go mod edit -replace=xxx=yyy

`
上一篇:幼儿园小班六一走队口号