Go基础语法

148 阅读3分钟

概要

本篇文章主要介绍Go基础语法, 包括变量、常量、方法、数据类型、指针、运算符、控制流等

变量

var a int //定义变量a为int
var a int = 10 //定义变量a为int,并初始化为10
var a = 10 //定义变量并初始化a为10,编译器根据10是int推断出变量a为int
a := 10 //更简练的写法,定义变量并初始化a为10,编译器根据10是int推断出变量a为int

//定义多个变量
var (
    a int
    b string
    c float
)

常量

//定义单个常量
const ErrCodeNotFound = "Not Found"

//定义同类常量
const (
    ErrCodeUndefined = itoa
    ErrCodeInternal
)

方法

定义方法的关键字是func

//两数相加
//参数 a和b都是int,返回值是int
func add(a, b int) int {
    return a + b
}

数据类型

基本数据

  • 整型
    • 有符合整型: int8、int16、int32、int64
    • 无符号整型:uint8(byte)、int16、uint32、uint64
  • 浮点型
    • float32
    • float64
  • 布尔型
    • bool 只有true(真)和false(假)两个值

其他数据类型

  • 数组array

    Go中的数组,申请的是一块连续的内存空间,大小不能改变。 一般情况Go中直接使用array的场景并不多。

    var a [2]int = {1, 2} //定义包含2个元素int数组
    
  • 字符串string

    Go中的string是只读的,可以通过len方法获取字符串的长度,底层实际上是struct

    var s1 string = "nihao"
    s2 := "hello"
    var s2_len = len(s2) //得到s2的字符串长度
    
  • 切片slice

    slice可以简单理解为能动态修改大小的array。slice有两个属性:容量和长度,分别可以使用cap和len方法获取,slice在Go中使用非常频繁

    var names []string //定义空slice,cap=0,len=0
    names = append(names, "zhangsan") //追加单个元素
    names = append(names, []string{"lisi", "wanger"}...) //追加slice
    capacity := cap(names) //容量,即分配的内存空间大小
    length := len(names) // 长度, 即当前有多少个元素
    newNames1 := names[0:2] //切片操作,获取从位置0到2的元素(左闭右开)即 [zhangsan lisi]
    nameNames2 := names[:2] //可以省略开始位置,默认从0开始
    nameNames3 := names[1:] //可以省略结束位置,默认到slice结束
    preAllocNames := make([]string, 0, 4) //定义容量为4的slice
    
  • map

    Go的map是个hashmap,内部是基于数组+链表的实现方案,在Go中使用非常频繁

    var m map[int]string //定义一个空map
    m = make(map[int]string) //使用之前必须make申请内存
    m[1] = "zhangsan"  //key=1 value=zhangsan
    name := m[1] //获取key=1的value
    name, ok := m[1] //第二个返回值ok标识key是否存在
    //遍历map
    for k, v := range m {
        fmt.Println(k, v)
    }
    
  • channel

    channel是Go中非常重要的一个数据类型,顾名思义作为通道,一般用于goroutine之间的通信。

    • 同步channel
    • 异步channel
    
    var syncChannel = make(chan int) //申请同步channel
    var buffer1Channel = make(chan int, 1) //申请缓冲空间为1的channel,和同步channel有很大区别
    var bufferChannel = make(chan int, 10) //申请缓冲空间为10的channel
    
    //同步channel常用场景
    go func() {
            //异步do something
            //结束之后通知主线程
            syncChannel <- 1
    }()
    
    //等待任务完成
    finished := <-syncChannel
    if finished == 1 {
            //do nothing
            fmt.Println("sync task finished")
    }
    
    //异步channel常用于生产者/消费者模式
    go func() {
            //生产者
            for i := 0; i < 10; i++ {
                    bufferChannel <- i
            }
            //关闭buffer
            close(bufferChannel)
    }()
    //消费数据
    for consumedRes := range bufferChannel {
            fmt.Println(consumedRes)
    }
    
    
  • 结构体struct

    Go中的结构体作用等同于其他语言的类,用来抽象复杂的数据类型

    //Person,有Name和Age两个属性,并且拥有GetAge()方法
    type Person struct {
        Name string
        Age  int
    }
    func(p Person) GetAge() int{
        return p.Age
    }
    
    //使用方法
    var p = Person{
        Name: "zhangsan",
        Age: 28,
    }
    fmt.Println(p.GetAge())
    
  • 函数func

    func其实也是一种特殊的数据类型,Go中闭包非常常见

    var add func(x, y int) int
    
    add = func(x, y int) int {
            return x + y
    }
    
    fmt.Println(add(10, 20))
    

指针

Go中的指针:变量的地址,不能对指针做运算,所以比较安全 由于Go方法传参都是值传递的方式(闭包是个例外)即形参是实参的一份copy, 如果想达到类似其他语言的引用传递的效果,需要使用到指针。

var a  = 1
var p = &a
fmt.Printf("p: %p\n", a, p)

func Change(a *int) {
    *a = 10
}

Change(&a)
fmt.Printf("a: %d\n",a) //打印a: 10

运算符

  • 算数运算符
    • 加法+ 、减法-、乘法*、除法/、取模%
  • 逻辑运算符
    • 逻辑与&&、逻辑或||、逻辑非!
  • 位运算符
    • 左移<<、右移>>、异或^、与&、或|
  • 关系运算符
    • 相等==、不相等!=、大于>、小于<、大于等于>=、小于等于<=

流程控制语句

分支语句

flag := true
if flag {
   //do something
} else {
    //do something
}

//多分支
a := 10
if a < 0 {
   //do something
} else if a > 0{
    //do something
} else {
    //do something
}

//switch分支
switch a {
case a<0: //无需break,会自动跳出分支,这个和其他语言不一样,切记
case a>0:
default:
}

循环语句

//for第一种形式
for i := 0; i<10; i++ {
}

i := 0
//第二种形式,类似其他语言的while
for i<10 {
    i++
}

//第三种形式,迭代,slice、map、channel都支持这种形式
for range c {
}