go基础语法及注意点 | 青训营笔记

63 阅读7分钟

这是我参与「第五届青训营」伴学笔记创作活动的第1天。今天复习了go的相关基础语法,并将一些值得注意的点记录了下来。

什么是go语言

  • 高性能、高并发
    • 不需借助复杂的第三方库即可开发高并发应用程序
  • 语法简单,学习曲线平缓
    • 类似C,去掉了表达式括号,循环只有一种方式
  • 丰富的标准库
    • 很高的稳定性和兼容性保障
    • 享受语言迭代带来的性能优化
  • 完善的工具链
    • 编译、代码格式化、错误检查、帮助文档、包管理、代码补充提示、
    • 单元测试框架:支持单元测试、性能测试、代码覆盖率等
  • 静态链接
    • 线上的容器环境中,部署体积非常小
  • 快速编译
    • 静态语言中几乎最快的编译速度
  • 跨平台
    • 常见的操作系统:Windows,Linux等
    • 移动平台:安卓,ios
    • 路由器、树莓派
    • 支持交叉编译
  • 垃圾回收

基础语法以及与其他语言的区别

go快速生成代码片段

  1. pkgm
package main

func main() {
	
}
  1. ff
fmt.Printf("", var)
  1. for
for i := 0; i < count; i++ {
	
}
  1. forr
for _, v := range v {
	
}
  1. fmain
func main() {
	
}

go中的if语句

  1. 不需要使用括号将条件包含起来
  2. 大括号{}必须存在,即使只有一行语句
  3. 左括号必须在ifelse的同一行
  4. if之后,条件语句之前,可以添加变量初始化语句,使用进行分隔

go中的switch语句

  1. 支持多条件匹配
  2. 不同的 case 之间不使用 break 分隔,默认只会执行一个 case
  3. 如果想要执行多个 case,需要使用 fallthrough 关键字,也可用 break 终止。
  4. 分支还可以使用表达式,例如:a>0

go中的for语句

  1. go语言中的for循环,只有for关键字,去除了像其他语言中的whiledo while.
  2. go中的for语句表达式不用加括号.
  3. go中的for语句的初始条件和结束条件都可以省略,在这种情况下,类似于其他语言的while语句.
  4. 只写for不写任何表达式相当于无限循环.
  5. Go语言中可以使用for range遍历数组、切片、字符串、map 及 channel。 通过for range遍历,数组、切片和字符串返回索引和值,map返回键和值,channel只返回通道内的值.

go中的循环控制语句

带标签的break,可以跳出多层作用域,不需要一层一层跳出.continuegoto也是如此.

go中的数组和切片

  1. 数组长度和元素类型共同组成数组的类型.
  2. 数组长度可以省略,使用...代替,初始化值的数量自动推断.
  3. 数组可以通过指定索引值的方式来初始化,未指定所有的默认未零值.
  4. 切片是一个拥有相同类型元素的可变长度的序列。切片可以理解为,可变长度的可以自动扩容的数组.
  5. 切片有自己的长度和容量,可以通过使用内置的len()函数求长度,内置的cap()函数求切片的容量.
  6. 切片可以使用append()函数添加元素。由于切片是引用类型,通过赋值的方式,会修改原有内容,go提供了copy()函数来拷贝切片。
    p := []int{1,2,3,4,5}
    q := make([]int,5)
    copy(q,p)
    

go中的map

  1. 判断map中某个键是否存在:
    value, ok := map[key]
    //判断ok是否为true即可判断key是否存在
    

go中的函数

  1. go语言中有3种函数:普通函数、匿名函数、方法(定义在struct上的函数)。
  2. go语言中不允许函数重载。
  3. go语言中的函数不能嵌套函数,但可以嵌套匿名函数。
  4. 函数是一个值,可以将函数赋值给变量,使得这个变量也成为函数。
  5. 函数可以作为参数传递给另一个函数。
  6. 函数的返回值可以是一个函数。
  7. 函数调用的时候,如果有参数传递给函数,则先拷贝参数的副本,再将副本传递给函数。
  8. 函数参数可以没有名称。

    函数参数

    1. go语言函数可以有0或多个参数,参数需要指定数据类型
    2. go语言是通过传值的方式传参的,意味着传递给函数的是拷贝后的副本。mapsliceinterfacechannel这些数据类型本身就是指针类型的,所以就算是拷贝传值也是拷贝的指针,拷贝后的参数仍然指向底层数据结构,所以修改它们可能会影响外部数据结构的值。
    3. go语言可以使用变长参数,有时候并不能确定参数的个数,可以使用变长参数,可以在函数定义语句的参数部分使用ARGS...TYPE的方式。这时会将...代表的参数全部保存到一个名为ARGS的slice中。

    函数返回值

    1. 函数可以有0或多个返回值,返回值需要指定数据类型,返回值通过return关键字来指定。
    2. return关键字中指定了参数时,返回值可以不用名称。如果return省略参数,则返回值部分必须带名称。
    3. 当返回值有名称时,必须使用括号包围,逗号分隔,即使只有一个返回值。
    4. 即使返回值命名了,return中也可以强制指定其它返回值的名称,也就是说return的优先级更高
    5. 命名的返回值是预先声明好的,在函数内部可以直接使用,无需再次声明。

    函数类型

    1. 可以用type关键字来定义一个函数类型。
    2. 可以使用函数类型来声明函数变量。

    匿名函数

    1. go语言函数不能嵌套,但是在函数内部可以定义匿名函数,实现简单的功能调用。匿名函数可以自己调用自己执行。
    func (参数列表)(返回值)
    

go中的指针

  1. go中的函数传参都是值拷贝,当期望修改某个变量的时候,可以创建一个指向该变量地址的指针。
  2. go中的指针不能进行偏移和运算。

go中的结构体

  1. go没有面向对象的概念,但可以使用结构体来实现面向对象编程的一些特性:继承、组合等。
  2. 结构体成员在没有赋值之前都是零值(0,0.0,false,nil等),可以使用.运算符来访问结构体成员。
  3. 如果结构体是临时使用,可以使用匿名结构体。
    package main
    
    import "fmt"
    
    func main() {
        var person struct {
            name string
            age int
        }
        person.name = "小杰"
        person.age = 18
        fmt.Printf("%v\n", person)
    }
    
  4. 可以使用new关键字创建结构体指针,访问结构体指针成员,也使用点运算符.
  5. go结构体可以像普通变量一样,作为函数的参数,传递给函数。直接传递结构体,将是一个副本,在函数内部不会改变外面结构体内容。当传递结构体指针时,在函数内部,能够改变外部结构体的内容。
  6. go语言没有面向对象编程思想,也没有继承关系,但是可以通过结构体嵌套来实现这种效果。

    go中的方法

    1. Go中的方法,是一种特殊的函数,定义于struct之上,方法和函数非常相似,只是多了一个接受类型:
      type mytype struct{}
      
      func (recv mytype) my_method(para) return_type {}
      func (recv *mytype) my_method(para) return_type {}
      
    2. 方法的receiver type并非一定要是struct类型,type定义的类型别名、slice、map、channel、func类型等都可以。
    3. struct结合它的方法就等价于面向对象中的类。只不过struct可以和它的方法分开,并非一定要属于同一个文件,但必须属于同一个包。
    4. 方法有两种接收类型:(T Type)(T *Type),它们之间有区别。
    5. go中没有方法重载(overload)的说法,也就是说同一个类型中的所有方法名必须都唯一。
    6. 如果receiver是一个指针类型,则会自动解除引用。
    7. 方法和type是分开的,意味着实例的行为(behavior)和数据存储(field)是分开的,但是它们通过receiver建立起关联关系。