3.函数、结构体、包
一、函数定义和调用
package mainimport ("fmt"
)func test() {fmt.Println("hello world")
}
func main() {test()
}
二、函数的参数
1.单个参数
func test(n int) {fmt.Println("传递进来的参数是", n)
}
func main() {test(10)
}
2.多个参数
func test(x, y int, s string) {fmt.Println(x)fmt.Println(y)fmt.Println(s)}
func main() {test(10, 20, "hello")
}
3.传递不定长参数(切片)
func test(x ...int) {fmt.Println(x)fmt.Println("x的类型为", reflect.TypeOf(x))
}
func main() {test(10, 20, 30, 40)
}
4.定义返回值
在形参括号的后边定义返回参数的类型
func test(x ...int) int {var sum intfor _, v := range x {sum += v}return sum
}
func main() {var sum = test(10, 20, 30, 40)fmt.Println("sum = ", sum)
}
5.函数变量的作用域
变量是先在函数内找,没有在在全局找。
三、匿名函数
var test2 = func() {fmt.Println("hello world")
}
四、高阶函数
1.高阶函数之函数作为参数
package mainimport ("fmt""time"
)func test(f func()) {var start = time.Now().Unix()f()var end = time.Now().Unix()t := end - startfmt.Printf("此程序使用%d秒的时间", t)
}func f1() {time.Sleep(time.Second * 1)
}func main() {test(f1)
}
2.高阶函数之函数作为返回值
这里不在写了,就是python中的装饰器概念。在go中,在一个函数内声明另外一个函数必须使用匿名函数
五、闭包
引用了一个外部的 非全局的自由变量的函数称为闭包函数。闭包主要解决的问题是 "全局变量污染"的问题
实例:
解释:i就是那个 外部的非全局的自由变量
conter的匿名函数就是闭包函数
func getCounter() func() {var i = 0counter := func() {i++fmt.Println(i)}return counter
}
func main() {counter := getCounter()counter()counter()counter()
}
六、结构体
go中结构体的概念和C中结构体概念一样。都是多个数据类型的集合
1.定义结构体
type 类型名 struct {字段1 字段1类型字段2 字段2类型…
}
例子:
type student struct {name stringage intgender stringclass string
}
2.实例化
2.1 先声明后赋值
type student struct {name stringage intgender stringclass string
}var s1 student
s1.name = "zhangsan"
s1.age = 20
fmt.Println(s1)
2.2 声明并赋值
这里讲了两种方式
type student struct {name stringage intgender stringclass string
}
var s = student{"zhangsan", 20, "boy", "1班"}
fmt.Println("s = ", s)
var s1 = student{name: "lisi", age: 21}
fmt.Println("s1 = ", s1)
3.结构体的方法接收器
(s stdent)就是和read方法绑定了
read是自定义方法名称
package mainimport "fmt"type student struct {name stringage int
}func (s student) read() {fmt.Printf("这是%s实例的接收器", s.name)
}func main() {s1 := student{"zhangsan", 10}s1.read()}
4.匿名字段
//正常我们按照格式来这样定义一个结构体
type student struct {name stringage int
}
4.1 普通匿名字段
匿名字段就是省略字段的名字,直接写类型,如下:
但是不建议这样做
type student struct {stringint
}func main() {var s1 = student{"zhangsan", 20}fmt.Println(s1.string, s1.int)
}
4.2 结构体嵌套的匿名字段
注意:s1是student结构体类型的实例,student中没有name字段,但是AA中有,所有s1可以直接s1.name这样使用
type AA struct {name string
}type student struct {stringintAA
}func main() {var s1 = student{"zhangsan", 20, AA{"lisi"}}fmt.Println(s1.string, s1.int, s1.name)
}
4.3 结构体的继承
结构体的继承就是面向对象中的继承,4.2当中的例子就是继承
七、包管理
go的包管理在
1.11之前使用的是go-path
1.11之后使用的是go-mod
1.包管理要求
1.go的包也是以目录为包,在目录下创建go文件,作为包文件
2.go文件中的函数的"首字母"必须大写。在go中规定 函数要想由外部导入和使用必须大写,首字母小写只能内部使用
2.制作一个包
这里直接使用go-mod模式管理包,不在使用go-path模式
test/
├── api
│ └── mysql.go
└── main.go
mysql.go文件内容如下:
注意:函数首字母必须大写
package api //这里的包名尽量和目录名称保持一致import "fmt"func Mysql_connect() {fmt.Println("正在连接mysql")
}
2.1 初始化包
在项目下初始化一个包:
格式如下:go mod init 自定义名称
PS E:\\code\\go\\test> go mod init mysite结构如下:
test/
├── api
│ └── mysql.go
├── go.mod
└── main.go
创建完毕后会发现报错
gopls was not able to find modules in your workspace.
When outside of GOPATH, gopls needs to know which modules you are working on.
解决办法:
1.ctrl + ,进入设置选项
2.“扩展” --> “Go”–>“Alternate Tools”–>“在setting.json中设置”
加入
"gopls": { "experimentalWorkspaceModule": true,
}
完整如下:
{"editor.fontFamily": "Consolas, monospace","explorer.confirmDelete": false,"workbench.colorTheme": "Default Light+","window.zoomLevel": 3,"go.alternateTools": {},"gopls": { "experimentalWorkspaceModule": true,}
}
重启vscode就可以了
2.2 在main.go中导包
注意:在go中,go会以文件中的package 后边定义的名字为包名,而不是像python那样以文件名称为基准
package mainimport "mysite/api"func main() {//直接调用,vscode会自动导包的路径api.Mysql_connect()
}
将包名从mysql.go中的api改为newapi,编辑器会自动导入成这样.
package mainimport ("fmt"newapi "mysite/api"
)func main() {newapi.Mysql_connect()fmt.Println("hello")
}
3.使用第三方包
//在项目目录下载第三方包
go get 包路径