# go-study **Repository Path**: qzcsu/go-study ## Basic Information - **Project Name**: go-study - **Description**: java程序员学go - **Primary Language**: Go - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2021-05-12 - **Last Updated**: 2025-12-24 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # go-study ## 介绍 java程序员学go ## 笔记 - go build 编译当前文件生成当前操作系统可执行的二进制文件 - go run 先编译再执行,但是不生成中间的二进制文件 -race 选项可以将执行的关键路径打印出来 - go build -o newName.exe hello.go go - 语言定义的变量,或者import包如果没有用到编译不能通过 - gofmt -w hello.go 格式化代码 - 官方编程文档:https://golang.org/pkg 同步的中文网站 https://studygolang.com/ - 使用go get软件的安装目录,默认取GOPATH下最先找到的src目录(如果是父子目录,即使你子目录写在前面也没用),如果GOPATH下找不到一个src目录则会在GOROOT下新建一个src目录将文件下载进去再安装,安装的目录就是和这个找到的src目录平级的bin目录 - 申明变量 var a,b,c int 申明并且赋初始值 var a,b,c=20, "hello", 666 变量定义可以不明确指定数据类型,进行类型推导 例如 str := "hello" ## 数据类型 - 基本数据类型 - 数值型 - 整数类型(int,int8,int16,int32,int64, uint,uint8,uint16,uint64, byte) - 字符型(没有专门的字符型,使用byte来保存单个字符) - 布尔型(bool) - 字符串(官方将string归属到基本数据类型) - 复杂数据类型 - 指针(Pointer) - 数组 - 结构体(struct) - 管道(Channel) - 函数 - 切片(slice) - 接口(interface) - map ## 数据类型使用 - 查看当前变量类型 num := 100 fmt.Printf("%T",num) - 查看一个变量占用空间(多少个字节) fmt.Printf("%d",unsafe.sizeof(num)) - 字符串拼接 +号要留在上面一行 ## 引包方式 ``` import ( "fmt" "unsafe" ) ``` - 取模运算 a%b = a-a/b*b ## 获取标准输入 ``` var name string //获取一行的值赋值给name fmt.Scanln(&name) ``` ## 条件判断 - 见代码 basic/if_main.go ``` var age = 18 if age > 10 { fmt.Println("年龄大于18") }if score := 90; score > 90 { fmt.Println("优秀") }else if score > 60 { fmt.Println("分数及格了") } ``` ``` key := 'a' switch key { case 'a': fmt.Println("是a") case 'b': fmt.Println("是b") default: fmt.Println("默认") } ``` ## 循环控制 - 见代码 basic/for_main.go ## 函数调用 - 见代码 advanced/func/* - 写代码时,打包 package 可以不与目录名一致 - 如果想要函数能跨包访问即使能import后调用,函数名首字母必须大写,引用包里面的变量也是一样 - 函数调用方式为 package.funcName() - 函数有多个返回值的时候,在调用的时候不想要某个结果可用下划线占位 _ - 函数也是一种数据类型,可以赋值给变量,相当于起别名,可以使用这个别名进行函数调用 - 支持自定义数据类型,即可以将一个函数取一个别名 - init 函数会在 main函数之前调用 - 函数中初始化顺序 全局变量初始化->init函数->main函数 ## 闭包 - 闭包就是一个函数与其相关的引用环境组合的一个整体(实体) - 见代码 advanced/closure/* ## defer - 见代码 advanced/defer/* - 就类似java中的 finally 块中的代码,延迟执行一些逻辑,用于释放资源,可以提前写在代码中,会以栈的形式压入,值是拷贝的 ## 字符串操作 - 见代码 basics/str_main.go ## 时间操作 - 见代码 basics/time_main.go ## 数组 - 见代码 advanced/array/* ## 随机数 - 见代码 basics/rand_main.go ## 切片 - 切片就类似与java中的List - 见代码 advanced/slice/* ## 映射 - 映射就类似与java中的Map - 见代码 advanced/map/* - map[key]函数返回结果可以是一个值,也可以是两个值,这是容易让人迷惑的地方。原因在于,如果获取一个不存在的 key 对应的值时,会返回零值。为了区分真正的零值和 key 不存在这两种情况,可以根据第二个返回值来区分 - 从一个 nil 的 map 对象中获取值不会 panic,而是会得到零值 ## 结构体 - 映射就类似与java中的class - 见代码 advanced/struct/* - 结构体中所有的字段在内存中都是连续的 - type 可以重定义类型,相当于取别名,类型之间可以强转,但是两个是不同的数据类型 例如: type myInt int - 方法:简单理解为作用在指定的数据类型上的函数 ## 封装继承 - 见代码 advanced/extend/* - 继承时候使用匿名结构体实现,B 继承 A B的实例为b,可以使用 b.A.Name,如果B中没有重复的属性Name 则可以简化为 b.Name - 继承的时候如果有同名的,会使用层级就近原则 - 有名结构体叫组合 - 多重继承即内部嵌套了多个匿名结构体 ## 接口 - 见代码 advanced/interface/* - 接口本身不能实例化赋值给一个变量 - 一个自定义类型可以实现多个接口 - 接口还可以继承 - 任意类型都实现了空接口,因此都可以赋值给空接口类型 ## 类型断言 - 见代码 basics/struct_assert.go ## 文件操作 - 见代码 advanced/file/* - 主要用os包下的File结构体 - File 是指针类型 ## json操作 - 见代码 basics/json_main.go ## 单元测试 - 见代码 advanced/test/* - 其实就是框架自己新生成一个main函数取调用对应的函数 - 编写单元测试代码的文件必须 _test.go 结尾 - 编写的单元测试的函数名必须以 Test 开头并且后面接的第一个字母必须大写字母 比如 TestSumTwo - 运行命令 go test 或 go test -v 也可以指定文件单元测试 - t.Fatalf 输出错误日志(并退出程序) t.Logf 记录日志 ## 协程goroutine - 见代码 advanced/goroutine/* - 主线程(进程)如果执行完了,协程会自动执行完 ## 管道channel - 见代码 advanced/channel/* - channel是引用类型,类似为一个队列 - 一个channel只能放一种数据类型。如果想放不同类型则申明为 空接口(即java中的Object类型)在取数时候可以强转回来 - 在没有协程使用情况下,队列空了不能再取,队列满了不能再加数据,否则都会报错 dead lock - 内置函数 close 关闭了管道 则不能加数据了,但是还能读数据 - 遍历管道 for range 必须管道关闭,类似把这个管道给静态化。如果不关闭则取完数据会继续取 则会报错 dead lock - 配合协程使用时,如果有一个协程写数据,一个协程读数据,写很快,读很慢,这时候不会死锁,只是队列会有一定阻塞 - 只读管道 var readChan chan<- int ; 只写管道 var writeChan <-chan int - 向缓冲区满的channel写数据和空channel中读数据都会导致goroutine阻塞 ## 反射 - 见代码 advanced/reflect/* - Type和Kind 如果是基本数据类型就相同,如果是引用类型就不同 ## 网络编程 - 见代码 advanced/net/* ## 锁与同步 - sync包提供了基本的同步基元,如互斥锁。除了Once和WaitGroup类型,大部分都是适用于低水平程序线程,高水平的同步使用channel通信更好一些。 - 见代码 advanced/sync/* ## 时间定时器 - 见代码 advanced/time/* ## 获取控制台标准输入输出 - 键代码 advanced/std/*