开发环境
Go 官网下载地址:https://golang.org/dl/
Go 官方镜像站(推荐):https://golang.google.cn/dl/
IDE
vscode 或者 goland
个人是新手觉得 goland 比较省事
语法
第一个 go 程序
关于导入与使用
1 2 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 变量
变量的声明
:=
简短声明变量,类型自动推导对应的数据类型
:=
只能在函数内部使用,不能在函数外部使用
其他的可以看看注释部分
1 2 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 的规则
1 2 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
注意返回值类型在后边,没有的话会报错
返回可以返回单个值,多个值,有形参的,也可以匿名的
1 2 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 导包路径问题
1 2 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()...") }
|
1 2 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()...") }
|
1 2 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
)。