公众号:Hoeller
教程中涉及到Go的知识点有:安装、变量、常量、特殊常量iota、切片、结构体、函数、方法、接口、指针。
安装
安装地址:golang.google.cn/dl/,按操作系统选择安装包
配置环境变量
c:Gobin
配置到Path
环境变量中Path
环境变量中验证版本
在命令行执行go version
输出版本则表示安装成功
dadudu@dadududeMBP ~ % go version
go version go1.21.3 darwin/arm64
Hello World
在任意地方新建文件hello.go,内容为
package main
import "fmt"
func main() {
fmt.Println("Hello, World")
}
然后运行go run hello.go
即可得到输出结果:"Hello, World"。
变量
go里面用var
来定义变量,名字在前,类型在后,并且可以一次定义多个变量
package main
import "fmt"
func main() {
var a string = "dadudu"
var b, c int = 1, 2
fmt.Println(a,b,c)
}
类型推导
也可以直接不写类型,go会根据值自动推导出变量的类型
var a = "dadudu"
var b, c = 1, 2
:=定义变量
因为有了类型推导,所以var关键字也可以不写,使用:=
来定义变量并赋值
package main
import "fmt"
func main() {
a := "dadudu"
b, c := 1, 2
fmt.Println(a, b, c)
}
修改变量
变量是可以修改的,直接用=
给变量赋不同的值就可以了
a = "xiaodudu"
注意:=
是用来定义变量的,不能用来修改变量。
常量
常量就是定义并初始化后就不能修改了,语法上跟变量一样,只是关键字用const
package main
import "fmt"
func main() {
const a = "dadudu"
//a = "xiaodudu" 此处编译报错
fmt.Println(a)
}
也可以一次性定义多个常量:
func main() {
const a, b, c = "dadudu", 1, 2
fmt.Println(a, b, c)
}
但是const关键字不能省略,不然就成了变量,但是如果确实有多个常量需要定义,或者定义枚举,还可以这样写
func main() {
const (
creating = 0
created = 1
unpaid = 2
paid = 3
)
fmt.Println(creating, created, unpaid, paid)
}
输出结果为:0 1 2 3
特殊常量iota
以上代码可以简化为:
func main() {
const (
creating = iota
created
unpaid
paid
)
fmt.Println(creating, created, unpaid, paid)
}
输出结果同样为:0 1 2 3
,赋值了iota的常量的值是0,后续的常量会自动加1,如果在四个常量中间新增了常量,那么五个常量的值会自动改变:
func main() {
const (
creating = iota
created
createFailed // 新增
unpaid
paid
)
fmt.Println(creating, created, createFailed, unpaid, paid)
}
输出结果为:0 1 2 3 4
,这样就能省掉程序员手动调整常量值的麻烦(想想Java中要怎么做....)
切片
go里有数值和切片两种类型,分别是这么定义的:
func main() {
a := [5]int{1, 2, 3, 4, 5} // 数组
b := []int{1, 2, 3, 4, 5} // 切片
fmt.Println(a, b)
}
数组长度不可变,切片长度可变,所以切片也叫做动态数组。
比如,可以给切片添加元素:
func main() {
a := [5]int{1, 2, 3, 4, 5} // 数组
b := []int{1, 2, 3, 4, 5} // 切片
b = append(b, 6)
fmt.Println(a, b)
}
输出结果为:
[1 2 3 4 5]
[1 2 3 4 5 6]
切片没有直接提供remove方法,可以通过append方法间接删除,以下代码会删除掉切片中下标为1的元素(2):
func main() {
a := [5]int{1, 2, 3, 4, 5} // 数组
b := []int{1, 2, 3, 4, 5} // 切片
b = append(b[:1], b[2:]...)
fmt.Println(a, b)
}
输出结果为:
[1 2 3 4 5]
[1 3 4 5]
另外,数组和切面都可以截取范围来访问元素:
func main() {
a := [5]int{1, 2, 3, 4, 5} // 数组
b := []int{1, 2, 3, 4, 5} // 切片
fmt.Println(a[1:4], b[2:5])
}
输出结果为:
[2 3 4]
[3 4 5]
结构体
如果你想要有一个“对象”,那么就可以定义一个结构体并构造出“对象”:
type User struct {
id int
name string
age int
}
func main() {
// 创建User对象
user := User{1, "dadudu", 18}
// 输出对象的name属性
fmt.Println(user.name)
}
函数与方法
Java只有方法,要么是静态方法(归属于类),要么是普通方法(归属于对象),go中分为函数与方法。
type User struct {
id int
name string
age int
}
func getNameAndAge(user User) (string, int) {
return user.name, user.age
}
func main() {
// 创建User对象
user := User{1, "dadudu", 18}
name, age := getNameAndAge(user)
fmt.Println(name, age)
}
以上getNameAndAge
就是一个函数,接收一个User类型对象,返回一个string和一个int,有点类似于Java的静态方法,不需要生成对象才能调用,直接调就可以了,但是强大的地方在于,一个函数可以有多个返回值(这个是真好用...)。
以下代码中的getNameAndId
就是一个方法,并且该方法跟User结构体绑定在一起了,而函数是没有和某个结构体绑定的,调用方法就需要对象才能调用
// 函数
func getNameAndAge(user User) (string, int) {
return user.name, user.age
}
// 方法
func (user User) getNameAndId() (string, int) {
return user.name, user.id
}
func main() {
// 创建User对象
user := User{1, "dadudu", 18}
name, age := getNameAndAge(user)
name, id := user.getNameAndId()
fmt.Println(id, name, age)
}
接口
Java中,需要在代码中先实现接口,然后必须实现接口中的方法,而在go中,一个结构体只要实现了某个接口的所有方法,那么这个结构体就是这个接口的“实现类”。
type Person interface {
getName() string
getAge() int
}
type User struct {
id int
name string
age int
}
func (user User) getName() string {
return user.name
}
func (user User) getAge() int {
return user.age
}
func main() {
var person Person = User{1, "dadudu", 18} // 赋值语句
fmt.Println(person)
}
以上代码中,由于给User结构体绑定了getName()
和getAge()
方法,所以User实现了Person接口中的两个方法,也就相当于User实现了Person接口,所以可以把User对象直接赋值给Person类型的变量。但凡注释掉其中一个方法,赋值语句都将报错。
指针
变量表示值,而指针表示值所在的内存地址,其实就是跟Java中的值传递和引用传递类似,比如以下代码:
func test(a int) {
a = 2
}
func main() {
a := 1
test(a) // 修改了a的值
fmt.Println(a)
}
最终输出的的a为1,虽然test函数中修改了a的值,但由于是指传递,传递给test函数的是一个副本,所以原本的a并没有发生改变。
而一旦把代码改成:
func test(a *int) {
*a = 2 // 将指针位置的值改为2
}
func main() {
a := 1
test(&a) // 传入a的指针
fmt.Println(a)
}
输出的a就是2了,因为传给test函数是a的指针,并且test函数中会把指针位置的值改为2。
极简Go教程就到这啦,大家如果觉得这种极简风格还可以,还想看其他语言的,记得点赞、收藏、分享告诉我哦~
欢迎大家关注我的公众号:Hoeller,第一时间接收我的原创技术文章,你将收获更多干货知识。