极简Go语言教程

2023年 10月 11日 36.4k 0

公众号:Hoeller

教程中涉及到Go的知识点有:安装、变量、常量、特殊常量iota、切片、结构体、函数、方法、接口、指针。

安装

安装地址:golang.google.cn/dl/,按操作系统选择安装包
image.png

配置环境变量

  • Windows将c:Gobin配置到Path环境变量中
  • Mac不需要额外配置
  • Linux将解压出来的目录中的bin目录配置到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,第一时间接收我的原创技术文章,你将收获更多干货知识。

    相关文章

    服务器端口转发,带你了解服务器端口转发
    服务器开放端口,服务器开放端口的步骤
    产品推荐:7月受欢迎AI容器镜像来了,有Qwen系列大模型镜像
    如何使用 WinGet 下载 Microsoft Store 应用
    百度搜索:蓝易云 – 熟悉ubuntu apt-get命令详解
    百度搜索:蓝易云 – 域名解析成功但ping不通解决方案

    发布评论