Go语言基础(一):Go语言介绍与变量、常量声明、函数|青训营笔记

134 阅读4分钟

这是我参与「第三届青训营 -后端场」笔记创作活动的的第1篇笔记;主要复习巩固了Go语言的特点、生态以及最常用的基础语法。

以下所贴代码均已测试运行

介绍GO

优势

  1. 高性能、高并发
  2. 语法简单、学习曲线平滑
  3. 丰富的标准库
  4. 完善的工具链
  5. 静态链接
  6. 快速编译
  7. 跨平台
  8. 垃圾回收机制
  1. 极简的部署

    • 直接编译成机器码
    • 不依赖其他库(其实就是取消动态库,全部使用静态库链接,一起打包成可执行文件)
    • 直接运行、即刻部署
  2. 静态类型语言

    • 就和C/C++一样,典型的后端编译型语言
    • 编译器即可检查出隐藏的大部分问题
  3. 语言层面的并发

    • 就是为了并发任务而设计的
  4. 强大的标准库

    • runtime 系统调度机制
    • 高效的GC垃圾回收(1.8以后加了三色标记和混合写屏障,效率提升)
  5. 语法简易而不简单

    • 25个关键字
    • c语言的简洁基因,内嵌c语法支持
    • 面向对象特征
    • 跨平台
  6. 知名开源项目

    1. 云计算基础设施
      • kubernets(k8s)
      • docker
      • etcd
      • consul
    2. 基础后端软件(存储)
      • tidb、influxdb
    3. 微服务
      • go-kit
      • micro
      • typhon

第一个GO 程序

Go 作为为并发而生的语言,通过创建 goroutine 进行并发操作,得益于协程的轻量程度,可以轻轻松松完成上万的并发任务

package main

import (
    "fmt" // 格式化IO
    "time"
)

func goFunc(i int) {
    fmt.Println("goroutine", i, "...")
}

func main() {
    for i := 0; i < 10000; i++ {
        go goFunc(i)
    }

    time.Sleep(time.Second) // 休眠1s
}

感受一下Go语言简易并强大的并发能力!

// 编译
go build xx.go

// 运行
./xx

// 合并上面的两步
go run xx.go

变量申明

声明单个变量

Go 和其他主流编程语言在声明变量的方式有所不同,Go会将变量类型放在变量名之前,并通过var关键字来声明这个变量。

通常有四种声明方式:
1. 默认参数的变量声明
go var a int
2.带默认值的变量声明
go var b int = 3
3.省略类型的变量声明,编译器会自动推导
go var c = 3.0 var d = 3
4.最常用的方式,利用 := 来进行变量声明,编译器会自动推导
go e := 100

/*
	四种变量的声明方式
*/

package main

import (
	"fmt"
)

func main() {
    // 方法一, 声明变量,默认值为0
    var a int
    fmt.Println("a = ", a)
    fmt.Printf("type of a = %T\n",a)

    // 方法二,声明变量,初始化一个值
    var b int = 3
    fmt.Println("b = ", b)
    fmt.Printf("type of b = %T\n",b)

    // 方法三,在初始化时,可以省去数据类型,通过值自动匹配(不推荐)
    var c = 3.0
    fmt.Println("c = ", c)
    fmt.Printf("type of c = %T\n",c)

    var d = 3
    fmt.Println("d = ", d)
    fmt.Printf("type of d = %T\n",d)

    var str = "hello"
    fmt.Println("str = ", str)
    fmt.Printf("type of str = %T\n",str)


    // 方法四:(最常用的方法)省略关键字var,直接自动匹配
    // 效果等同于 var e int = 100 , 声明变量并赋初值
    e := 100
    fmt.Println("e = ", e)
    fmt.Printf("type of e = %T\n",e)
}

tips:

声明全局变量时,方法一到三没有问题,同之前的所有语言一样,而方法四不能声明全局变量( := 只能够在函数体中使用,不能声明全局变量 )

声明多个变量


1. 相同类型的变量可以只写一次变量类型:
go var x,y int = 100, 200
2. 或者根本不带类型(:= 也支持该写法):
go var kk, ll = 300,"abc"
3. 甚至可以用小括号定制化:
go var ( vv int = 400 jj bool = true str = "asd" )

package main

import (
    "fmt"
)

func main() {
    // 声明多个变量
    var x,y int = 100, 200
    fmt.Println(x," ", y)

    var kk, ll = 300,"abc"
    fmt.Println(kk, " ", ll)


    var (
            vv int  = 400
            jj bool = true
            str = "asd"
    )
    fmt.Println(vv, " ", jj, " ", str)
}

常量的声明与定义

其实就是将关键字改为const

由于Go语言没有枚举类型,所以通过常量const和关键字iota来实现枚举

tips: iota 关键字只能配合const使用,他的声明周期只在const的()范围中

可以在const() 中添加关键字iota, 每行的iota都会累加1 第一行的iota 默认值为 0

具体使用方式可以运行下列代码 :

package main

import (
	"fmt"
)

func main() {
    // 声明常量(只读属性)
    const x int = 100
    fmt.Println(x)

    // 通过const 变相实现枚举类型
    const (
        // 可以在const() 中添加关键字iota, 每行的iota都会累加1
        // 第一行的iota 默认值为 0
        // iota 只会出现在const 的() 中,配合const 使用
        BEIJING = iota
        SHANGHAI 
        SHENZHEN 
    )	
    fmt.Printf("BEIJING = %d,SHANGHAI = %d,SHENZHEN = %d\n", BEIJING, SHANGHAI, SHENZHEN)

    const (
        a, b = iota+1,iota+2
        c, d
        e, f

        g,h  = iota*2, iota*3
        i,k
    )
    fmt.Println(a," ",b," ",c," ",d)
    fmt.Println(e," ",f," ",g," ",h)
    fmt.Println(i," ", k)
}

函数

go 语言使用关键字func 来定义一个函数,关键字package 表示当前所在的包的名称,通过import来导入函数所需要的包,函数的返回值是写在参数表的后面,Go还支持多返回值的函数,其中返回值可以匿名。

package main

import (
	"fmt"
)

// 返回值写在 () 之后,没有返回值就不写
func fool (a string, b int ) int {
    fmt.Println("------fool---------")
    fmt.Println("a = ",a," b = ",b)
    return 3
}

// 多个匿名返回值
func fool2(a string, b int) (int,string) {
    fmt.Println("------fool2---------")
    return b,a
}

// 多个带形参名的返回值
// r1 r2 作用域是fool3的整个函数体内
func fool3(a int, b int) (r1 int, r2 int) {
    fmt.Println("------fool3---------")
    fmt.Println(r1, " ", r2) // r1 r2 属于函数的形参,初始化默认值(0)
    r1 = b 
    r2 = a
    return r1,r2
}

// 如果返回值是同类型,类型可以合并写
func fool4(a int, b int) (r1,r2 int) {
    fmt.Println("------fool4---------")
    r1 = 3
    r2 = 4
    return r1, r2
}


func main() {
    a := fool("ab",5);
    fmt.Println(a);

    ret1,ret2 := fool2("cd",10)
    fmt.Println(ret1," ",ret2)

    ret3,ret4 := fool3(1,2)
    fmt.Println(ret3," ", ret4)

    ret5,ret6 := fool4(1,2)
    fmt.Println(ret5," ", ret6)
}

错误处理

go 语言没有warning和异常捕获这种机制,只有error,标准库提供了errors包,使得所有的error可以使用if else 来判断处理,标准库中大量使用到函数返回一个error这种设计,

package main

import (
    "errors"
    "fmt"
)

func testError(data string) (a string, err error) {
    if data == "str" {
                    return data,nil
    } else {
                    return "",errors.New("this is error")
    } 
}

func main() {
    var a string = "tr"
    data, err := testError(a)
    if err == nil {
            fmt.Println("data is",data)
    } else {
                    fmt.Println(err)
    }
}

引用

「Go 语言上手-基础语言」第三届字节跳动青训营 - 后端专场

8小时转职Golang工程师