Go 语言入门指南:基础语法和常用特性解析(1) | 青训营

98 阅读7分钟

go基础语法

Go 语言的基础组成
  1. 包声明(Package Declaration) :Go语言的每个源文件都属于一个包。包声明指定了当前源文件所属的包,并决定了该文件中的代码在编译时如何组织和链接。
  2. 引入包(Import Packages) :通过引入其他包,我们可以使用其他包中定义的函数、变量和类型。使用import关键字来引入包,并可通过import语句的方式引入多个包。
  3. 函数(Functions) :函数是Go语言中的基本执行单元。我们可以定义自己的函数,并通过函数名来调用它们。函数通常接收参数并返回一个值。
  4. 变量(Variables) :变量用于存储和操作数据。在Go语言中,我们需要先声明变量,然后才能使用它们。变量可以是基本类型(如整数、浮点数、字符串)或自定义类型。
  5. 语句和表达式(Statements & Expressions) :语句是执行特定操作的代码单元,例如赋值语句、条件语句和循环语句。表达式用于计算值,可以由常量、变量、运算符和函数调用等组成。
  6. 注释(Comments) :注释是对代码的解释和说明,对于开发者来说是很重要的。在Go语言中,我们可以使用//来添加单行注释,或使用/* */来添加多行注释。
变量
  • Go 语言变量名由字母、数字、下划线组成,其中首个字符不能为数字。

  • Go语言是一门强类型语言,每一个变量都有它自己的变量类型

  • 常见的变量类型

    • 字符串
    • 浮点型
    • 整数型
    • 布尔型
  • 变量声明

    • 指定变量类型,如果没有初始化,则变量默认为零值。

       /*
       var v_name v_type //声明变量
       v_name = value  //赋值
       */
       var t1 string = "hello"
       var t2 int = 1
       var t3 bool = true
      
    • 根据值自行判定变量类型。

       /*
       var v_name = value  
       */
       var t1 = "hello"
       var t2 = 1
       var t3 = true
      
    • 使用 := 声明变量

       /*
       v_name := value
       */
       t1 := "hello"
       t2 := 1
       t3 := true
      
    • 多变量声明

       //类型相同多个变量, 非全局变量
       var vname1, vname2, vname3 type
       vname1, vname2, vname3 = v1, v2, v3
       ​
       var vname1, vname2, vname3 = v1, v2, v3 // 和 python 很像,不需要显示声明类型,自动推断
       ​
       vname1, vname2, vname3 := v1, v2, v3 // 出现在 := 左侧的变量不应该是已经被声明过的,否则会导致编译错误
       ​
       // 这种因式分解关键字的写法一般用于声明全局变量
       var (
           vname1 v_type1
           vname2 v_type2
       )
      
常量
  • 常量中的数据类型只可以是布尔型、数字型(整数型、浮点型和复数)和字符串型。

  • 常量的定义格式

     /*
     const identifier [type] = value
     */
     // 显式类型定义:
     const t1 string = "abc"
     // 隐式类型定义:
     const t2 = "abc"
     // 多个相同类型的声明
     const c_name1, c_name2 = value1, value2
    
  • 常量还可以用作枚举

     const (
         t1 = iota
         t2 = 1
         t3 = 2
     )
    

    iota,特殊常量,可以认为是一个可以被编译器修改的常量。第一个 iota 等于 0,每当 iota 在新的一行被使用时,它的值都会自动加 1

常用的数据类型
  1. 整数,int

    支持的整型分类很细,主要差异是占用的存储空间不同。基于有无符号列出为:

    • 有符号的:int,int8,int16,int32,int64
    • 无符号的:uint,uint8,uint16,uint32,uint64

    其中int, unit是基于处理器架构的。意味着会根据处理器来确定是32bit还是64bit。 使用时,常常使用int。或者使用int32保证兼容。 在类型推导时,推导的整型为int,其他长度整型需要在定义变量时强制声明。(整型的默认值为0)

  2. 浮点数,float

    支持IEEE-754标准浮点数。支持32bit和64bit的浮点数float32和float64。 在类型推导时,推导的浮点型为float64。float32需要在定义变量时强制声明。(浮点数的默认值为0)

  3. 复数,complex

    原生支持复数。 支持32bit+32bit复数complex64,和64bit+64bit的复数complex128。

     // 定义复数
     var t1 complex64 = complex(1, 2)
     var t2 complex128 = complex(1, 2)
     t3 := 1 + 2i
     t4 := complex(float64(1), float64(2))
     // 获取实部和虚部
     realPart := real(t1)
     imagPart := imag(t2)
    
  4. 字符串,string

    原生支持字符串。使用双引号("")或反引号()定义,内部是utf-8编码。 双引号:"", 用于单行字符串。 反引号:,用于定义多行字符串,内部会原样解析。 示例:

     // 单行
     "test"
     // 多行
     `
     test
     test
     `
    

    字符串支持转义字符,列表如下: \r 回车符(返回行首) \n 换行符(直接跳到下一行的同列位置) \t 制表符 ' 单引号 " 双引号 \ 反斜杠 * \uXXXX Unicode字符码值转义

  5. 布尔型,bool

    布尔型的值只可以是常量 true 或者 false

  6. 指针,pointer

    指针类型用于存储变量地址。使用运算符 & , *完成操作。 使用运算符 p:=&v 可以获取v变量的地址。p中的数据格式类似0xc0000b9528,是一个内存地址的16进制表示。 使用运算符 *p 可以获取指针p指向变量v的值。

    在Go语言中,指针主要用于: 类型指针,对指针指向的数据进行修改。函数调用时传递参数使用指针,避免值传递拷贝额外数据。注意类型指针不能进行偏移和运算。 切片,由指向起始元素的原始指针、元素数量和容量组成。

  7. 数组,array

    数组是一段固定长度的连续内存区域。是具有相同类型数据元素序列。元素类型支持任意内置类型。 数组从声明时就确定长度,可以修改数组元素,但是数组不可修改长度。 使用 [长度]类型 进行数组的声明。 示例:

     // 默认值初始化
     var nums [4]int // [0 0 0 0]
     // 数组常量初始化数组
     var position = [4]string{"east", "south", "west", "north"}
     var arrAge = [5]int{18, 20, 15, 22, 16}
     var arrKeyValue = [5]string{3: "Chris", 4: "Ron"}
     // 自动确定长度
     var position = [...]string{"east", "south", "west", "north"}
    
  8. 切片,slice

    • 切片可以看作是数组的引用,切片和数据对应的是同一份数据,如果原数组的数据发生变化,那么会连带着切片中的数据一起变化。

    • 左闭右开

    • 切片声明:var identifier []type

    • len()函数计算切片长度,cap()函数计算切片容量,append()函数进行切片追加,copy()函数进行拷贝

    • 切片使用

      • 从数组中产生切片

         var a [10]int
         var s []int= a[:]
         s = a[:4]
         s = a[1:]
        
      • 直接定义切片

         s := []int{1,2,3,4,5,6}
        
      • make方法创建切片

         /*
         make 的使用方式是:func make([]T, len, cap),其中 cap 是可选参数。
         */
         s := make([]int, 0, 5)
        
    • 二维切片

       mat := make([][]int, 10)
       for i := 0; i < 10; i++ {
         mat[i] = make([]int, 10)
       }
      
  9. 映射,map

    • Map 是一种无序的键值对的集合。

    • Map 是引用类型,如果将一个 Map 传递给一个函数或赋值给另一个变量,它们都指向同一个底层数据结构,因此对 Map 的修改会影响到所有引用它的变量。

    • 定义map

       /* 使用 make 函数 */
       map_variable := make(map[KeyType]ValueType, initialCapacity)
      

      其中 KeyType 是键的类型,ValueType 是值的类型,initialCapacity 是可选的参数,用于指定 Map 的初始容量。Map 的容量是指 Map 中可以保存的键值对的数量,当 Map 中的键值对数量达到容量时,Map 会自动扩容。如果不指定 initialCapacity,Go 语言会根据实际情况选择一个合适的值。

    • 获取元素:

       // 获取键值对
       v1 := m["apple"]
       v2, ok := m["pear"]  // 如果键不存在,ok 的值为 false,v2 的值为该类型的零值
      
    • 修改元素:

       // 修改键值对
       m["apple"] = 5
      
    • 获取 Map 的长度:

       // 获取 Map 的长度
       len := len(m)
      
    • 遍历 Map:

       // 遍历 Map
       for k, v := range m {
           fmt.Printf("key=%s, value=%d\n", k, v)
       }
      
    • 删除元素:

       // 删除键值对
       delete(m, "banana")
      
  10. 结构体,struct

    • Go 语言中数组可以存储同一类型的数据,但在结构体中我们可以为不同项定义不同的数据类型。

    • 结构体是由一系列具有相同类型或不同类型的数据构成的数据集合。

    • 定义结构体

      结构体定义需要使用 type 和 struct 语句。struct 语句定义一个新的数据类型,结构体中有一个或多个成员。type 语句设定了结构体的名称。结构体的格式如下:

       type struct_variable_type_name struct {
          member definition
          member definition
          ...
          member definition
       }
       ​
      
    • 结构体方法

      Go语言中的方法(Method)是一种作用于特定类型变量的函数。这种特定类型变量叫做接收器(Receiver)

       func (接收器变量 接收器类型) 方法名(参数列表) (返回参数){
       }
      

      接收器类型可以是带指针的与不带指针的,带指针的会对结构体修改

  11. 接口,interface

    • interface 是方法声明的集合
    • 任何类型的对象实现了在interface 接口中声明的全部方法,则表明该类型实现了该接口。
    • interface 可以作为一种数据类型,实现了该接口的任何对象都可以给对应的接口类型变量赋值。
    • interface 可以被任意对象实现,一个类型/对象也可以实现多个 interface
    • interface 定义的方法不能重载,如 eat() eat(s string) 不能同时存在

       //Info 是一个接口,它有方法 Getinfo()string
       type Info interface {
         Getinfo() string
       }
      
  12. 函数,func()

    • 函数定义

      Go 语言函数定义格式如下:

       func function_name( [parameter list] ) [return_types] {
          函数体
       }
      

Go语言函数支持递归使用

条件语句
  • if语句

     if 布尔表达式 {
         ···
     }
    
  • if···else语句

     if 布尔表达式 {
         ···
     }else 布尔表达式{
         ···
     }
    
  • Switch语句

     switch var1 {
         case val1:
             ...
         case val2:
             ...
         default:
             ...
     }
    

    与C语言不同的是,Go语言中的switch 默认情况下 case 最后自带 break 语句,匹配成功后就不会执行其他 case

循环语句
  • 格式

     // 1、类似C语言的for循环
     for init; condition; post { }
     // 2、类似C语言的while循环
     for condition {}
     // 3、死循环
     for {}
     // 4、可以使用for与range对 slice、map、数组、字符串等进行遍历
     for key, value := range oldMap {
         newMap[key] = value
     }
    
  • 与C语言类似可以使用break跳出循环,使用continue继续循环