开发环境
Go 官网下载地址:https://golang.org/dl/
Go 官方镜像站(推荐):https://golang.google.cn/dl/
IDE
vscode 或者 goland
个人是新手觉得 goland 比较省事
语法
第一个 go 程序
关于导入与使用
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 
 | package main
 
 import "fmt"
 import "time"
 
 
 
 
 
 
 
 
 
 
 
 func main() {
 
 fmt.Println("hello world")
 
 time.Sleep(1 * time.Second)
 }
 
 | 
var 变量
变量的声明
:=简短声明变量,类型自动推导对应的数据类型
:=只能在函数内部使用,不能在函数外部使用
其他的可以看看注释部分
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 
 | package main
 
 import "fmt"
 
 
 var ga int = 100
 var gb = 200
 
 
 
 
 
 
 
 func main() {
 
 var a int
 fmt.Println("a =  ", a)
 fmt.Printf("type of a = %T\n", a)
 
 
 var b int = 100
 fmt.Println("b = ", b)
 fmt.Printf("type of b = %T\n", b)
 
 
 var c = 200
 fmt.Println("c = ", c)
 fmt.Printf("type of c = %T\n", c)
 
 var cc = "abcd"
 fmt.Printf("cc = %s, type of cc = %T\n", cc, cc)
 
 
 d := 300
 fmt.Println("d = ", d)
 fmt.Printf("type of d = %T\n", d)
 
 f := "abc"
 fmt.Printf("f = %s, type of f = %T\n", f, f)
 
 g := 3.14
 fmt.Printf("g = %f, type of g = %T\n", g, g)
 
 
 fmt.Println("ga = ", ga)
 fmt.Printf("type of ga = %T\n", ga)
 fmt.Println("gb = ", gb)
 fmt.Printf("type of gb = %T\n", gb)
 
 
 
 
 var x, y, z int = 1, 2, 3
 fmt.Println("x = ", x)
 fmt.Println("y = ", y)
 fmt.Println("z = ", z)
 
 var xx, yy = 100, "abcde"
 fmt.Println("xx = ", xx, "yy = ", yy)
 
 
 var (
 vv int  = 100
 jj bool = true
 )
 fmt.Println("vv = ", vv, "jj = ", jj)
 }
 
 | 
常量 const 与枚举递增 iota
常量(const)声明,只读属性
const 来定义枚举类型
可以在 const() 添加关键字 iota,每行的 iota 都会累积 1,第一行 iota 的值是 0
枚举的值都符合 iota 的规则 
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 
 | package main
 
 import "fmt"
 
 
 
 
 
 
 
 
 
 
 const (
 
 
 BEIJING   = 10 * iota
 SHANGHAI
 GUANGZHOU
 )
 
 const (
 a, b = iota + 1, iota + 2
 c, d
 e, f
 
 g, h = iota * 2, iota * 3
 i, j
 
 )
 
 func main() {
 
 const length int = 10
 
 fmt.Println("length = ", length)
 
 
 
 fmt.Println("BEIJING = ", BEIJING)
 fmt.Println("SHANGHAI = ", SHANGHAI)
 fmt.Println("GUANGZHOU = ", GUANGZHOU)
 
 fmt.Println("a = ", a, "b = ", b)
 fmt.Println("c = ", c, "d = ", d)
 fmt.Println("e = ", e, "f = ", f)
 fmt.Println("g = ", g, "h = ", h)
 fmt.Println("i = ", i, "j = ", j)
 
 }
 
 | 
函数 function
注意返回值类型在后边,没有的话会报错
返回可以返回单个值,多个值,有形参的,也可以匿名的
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 
 | package main
 
 import "fmt"
 
 
 func foo1(a string, b int) int {
 fmt.Println("a = ", a)
 fmt.Println("b = ", b)
 
 c := 100
 
 return c
 }
 
 
 func foo2(a string, b int) (int, int) {
 fmt.Println("a = ", a)
 fmt.Println("b = ", b)
 
 return 666, 777
 }
 
 
 func foo3(a string, b int) (c int, d int) {
 fmt.Println("---- foo3 ----")
 fmt.Println("a = ", a)
 fmt.Println("b = ", b)
 
 
 fmt.Println("c = ", c)
 fmt.Println("d = ", d)
 
 c = 100
 d = 200
 
 return
 }
 
 
 fmt.Println("---- foo4 ----")
 fmt.Println("a = ", a)
 fmt.Println("b = ", b)
 
 
 c = 100
 d = 200
 
 return
 }
 func main() {
 c := foo1("abc", 100)
 
 fmt.Println("c = ", c)
 
 ret1, ret2 := foo2("111", 222)
 fmt.Println("ret1 = ", ret1, " ret2 = ", ret2)
 
 ret1, ret2 = foo3("abc", 100)
 fmt.Println("ret1 = ", ret1, " ret2 = ", ret2)
 
 ret1, ret2 = foo4("abd", 300)
 fmt.Println("ret1 = ", ret1, " ret2 = ", ret2)
 }
 
 | 
import 导包路径问题
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 
 | package lib1
 
 import "fmt"
 
 
 func Lib1Test() {
 fmt.Println("lib1Test()...")
 }
 
 func init() {
 fmt.Println("lib1.init()...")
 }
 
 | 
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 
 | package lib2
 
 import "fmt"
 
 
 func Lib2Test() {
 fmt.Println("lib2Test()...")
 }
 
 func init() {
 fmt.Println("lib2.init()...")
 }
 
 | 
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 
 | package main
 
 import (
 "go_learning/5_init/lib1"
 "go_learning/5_init/lib2")
 
 func main() {
 lib1.Lib1Test()
 lib2.Lib2Test()
 }
 
 | 
注意一定要有 go.mod 的存在,不然 go 会去 gopath 里找包然后报错
这里是gpt的解答:
在 Go 中,如果没有 go.mod 文件,Go 会根据 GOPATH 模式 来查找包,而不是使用 Go Modules(模块化依赖管理)。这是 Go 1.11 之前的行为,而现代 Go 项目通常推荐使用 Go Modules。
为什么没有 go.mod 会去其他路径找包?
- 历史行为(GOPATH 模式): - 
- 在 Go Modules 引入之前(Go 1.11 之前),Go 依赖 GOPATH环境变量来管理包。
- 所有第三方包和本地项目都必须放在 $GOPATH/src下,编译器会从GOPATH中查找包。
 
- 查找顺序: - 
- 如果没有 go.mod,Go 会按以下顺序查找包:
- 标准库(如 fmt、net/http等,位于GOROOT/src)。
- GOPATH/src目录:尝试在- $GOPATH/src/go_learning/5_init/lib1中查找包。
- 当前目录(但通常不适用,除非是相对路径导入)。
 
 
- 你的错误信息分析: | 1
 | 1_main.go:4:2: package go_learning/5_init/lib1 is not in std (/opt/homebrew/opt/go/libexec/src/go_learning/5_init/lib1)
 |  
 
- 
- 编译器在标准库(std)和GOPATH中都没找到go_learning/5_init/lib1,因此报错。
 
解决方法
1. 启用 Go Modules(推荐)
在项目根目录(如 go_learning/)下运行:
这会生成 go.mod 文件,之后 Go 会基于模块路径解析本地包,不再依赖 GOPATH。
2. 检查包路径
确保导入路径与模块名一致。例如:
- 如果 go.mod声明module go_learning,则导入应为:| 1
 | import "go_learning/5_init/lib1"
 |  
 
3. 避免依赖 GOPATH
- 现代 Go 项目应始终使用 go.mod,避免将代码放在$GOPATH/src下。
关键区别:GOPATH vs Go Modules
| 特性 | GOPATH 模式 | Go Modules 模式 | 
| 依赖管理 | 代码必须放在 $GOPATH/src | 任意目录,通过 go.mod管理 | 
| 导入路径 | 从 GOPATH/src开始查找 | 基于模块名( module xxx) | 
| 版本控制 | 手动管理 | 通过 go.mod和go.sum | 
| 本地包引用 | 必须符合 GOPATH结构 | 支持相对路径或模块路径 | 
总结
- 没有 go.mod:Go 回退到GOPATH模式,导致编译器去GOPATH/src或标准库中查找包。
- 正确做法:始终使用 go mod init初始化项目,确保依赖和本地包能被正确解析。
如果仍有问题,请检查项目结构和 go.mod 内容,或提供更多上下文进一步分析。
同时调用的方法和参数也要是大写的首字母,不然不能通过 import 调用
- 大写:允许跨包访问(类似 public)。
- 小写:仅限当前包内使用(类似 private)。