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

157 阅读8分钟

这篇文章来讲下Go语言的基础内容,整体包括golang初识,golang的第一个程序,go项目的编译和构建,最后就是go语言的基础知识(一些语法基础)

golang初识 :

golang没有那些内容:

  1. 没有类(class) : 用结构体替代
  2. 没有方法重载
  3. 没有继承
  4. 没有枚举类型
  5. 没有try/catch
  6. 没有泛型

golang有什么:

  1. struct(结构体)
  2. 结构体的内嵌
  3. 常量
  4. defer/recover/panic
  5. interface{}
  6. 接口

golang特性 :

  1. 头等函数,允许将函数分配给变量,作为其他函数的入参,返回值,函数可以是对象,函数也可以是类型
  2. 并行操作非常方便,通过go关键字启动协程
  3. 通过通讯共享内容
  4. 多路复用,channel的多路复用

golang语言特性

Golang的优势

极简单的部署方式:可直接编译成机器码、不依赖其他库、直接运行即可部署。

静态类型语言,编译的时候可以检查出大多数问题。

语言层面的并发:天生的基因支持、充分的利用多核

// Go 语言实现并发的代码

func goFunc(i int) {

fmt.Println("goroutine ", i, " ...")

}

func main() {

for i := 0; i < 1000; i++ {

go goFunc(i) // 开启一个并发协程

}

time.Sleep(time.Second)

}

强大的标准库

runtime 系统调度机制、高效的 CG 垃圾回收、丰富的标准库

Golang 的应用场景

1、云计算基础设施领域:

代表项目:docker、kubernetes、etcd、consul、cloud flare CDN、七牛云存储 等。

2、基础后端软件:

代表项目:tidb、influxdb、 cockroach 等。

3、微服务

代表项目:go-kit、 micro、 monzo bank 的 typhon、bilibili 等。

4、互联网基础设施

代表项目:以太坊、hyperledger 等。

有编程经验如何快速学习go

  1. 那些内容是golang没有的
  2. 使用golang的特性的替代方案
  3. golang面向对象编程
  4. golang多态的实现

golang的第一个程序 :

// hello.go

package main // 在go中,每个文件都必须归属于一个包

import "fmt" //引入一个包,包名fmt,引入该包后,就可以使用fmt包的函数,比如fmt.Println()

func main() { // func 是一个关键字,表示一个函数,main是函数名,是我们程序的入口

fmt.Println("Hello World!")//调用fmt包中的函数Println()输出Hello World

}

变量
  • Go 语言变量名由字母、数字、下划线组成,其中首个字符不能为数字。

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

  • 常见的变量类型

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

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

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

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

      go
      复制代码
       /*
       v_name := value
       */
       t1 := "hello"
       t2 := 1
       t3 := true
      
    • 多变量声明

      go
      复制代码
       //类型相同多个变量, 非全局变量
       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
       )
      
常量
  • 常量中的数据类型只可以是布尔型、数字型(整数型、浮点型和复数)和字符串型。

  • 常量的定义格式

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

    go
    复制代码
     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。

    go
    复制代码
     // 定义复数
     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编码。 双引号:"", 用于单行字符串。 反引号:,用于定义多行字符串,内部会原样解析。 示例:

    text
    复制代码
     // 单行
     "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

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

    go
    复制代码
     // 默认值初始化
     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()函数进行拷贝

    • 切片使用

      • 从数组中产生切片

        go
        复制代码
         var a [10]int
         var s []int= a[:]
         s = a[:4]
         s = a[1:]
        
      • 直接定义切片

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

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

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

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

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

    • 定义map

      go
      复制代码
       /* 使用 make 函数 */
       map_variable := make(map[KeyType]ValueType, initialCapacity)
      

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

    • 获取元素:

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

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

      go
      复制代码
       // 获取 Map 的长度
       len := len(m)
      
    • 遍历 Map:

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

      go
      复制代码
       // 删除键值对
       delete(m, "banana")
      
  10. 结构体,struct

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

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

    • 定义结构体

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

      text
      复制代码
       type struct_variable_type_name struct {
          member definition
          member definition
          ...
          member definition
       }
       ​
      
    • 结构体方法

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

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

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

  11. 接口,interface

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

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

    • 函数定义

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

      text
      复制代码
       func function_name( [parameter list] ) [return_types] {
          函数体
       }
      

Go语言函数支持递归使用

条件语句
  • if语句

    text
    复制代码
     if 布尔表达式 {
         ···
     }
    
  • if···else语句

    text
    复制代码
     if 布尔表达式 {
         ···
     }else 布尔表达式{
         ···
     }
    
  • Switch语句

    text
    复制代码
     switch var1 {
         case val1:
             ...
         case val2:
             ...
         default:
             ...
     }
    

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

循环语句
  • 格式

    go
    复制代码
     // 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继续循环

总结

这篇文章是一次实践记录和工具使用练习,上述总结了go语言入门指南的大部分知识点