go语法基础

本文详细介绍了Go语言中的变量声明与初始化,包括标准声明、简化声明、批量声明以及指针、数组、切片、函数类型的变量声明。此外,还讨论了Go语言的变量生命周期、逃逸分析以及全局变量的使用规则。同时,文章涵盖了常量的声明方式,如基本声明、iota常量生成器,并展示了如何自定义枚举类型。最后,提到了Go语言中错误处理的多重赋值方式及其在内存管理中的应用。
摘要由CSDN通过智能技术生成

Go语言的变量

  1. 标准声明并初始化
var 变量名 [类型可选填] = 初始值

编译器会自动对类型进行推断

  1. 简化声明并初始化
变量名 := 初始值

注意:简化声明并初始化相当于先声明变量,再进行赋值,是两步操作。故而只能在函数内使用!

  1. 批量声明并初始化
var (
    name,company = "jarvis","tencent"   // string,string
    age = 23    // int
)

如果声明了变量但未使用,Go 编译不会通过,会抛出错误

go变量声明书写方式的原因:

与C/C++\Java等语言反其道而行之的原因:Go语言的变量声明更符合英文语言的表达方式,不经意间就解决了复杂声明的问题,有别于C/C++还需要知道’优先级’原则、'right-left’规则等,只需要直接从左往右理解即可。避免了左右兼顾,螺旋式理解的难点。

// 指针变量声明
C                    Golang
int *x;     <>      var x *int    //x is a pointer to int
int **p;    <>      var p **int  //p is a pointer to pointer to int 

// 数组/切片(go)变量声明
C                      Golang
int a[5];     <-->    var a [5]int       //a is an array[5] of int
int a[5][3];  <-->    var a [5][3]int   //a is an array[5] of array[3] of int
                      var s []int      //s is a slice of int(C语言中无slice类型)

// 函数类型变量声明                 
C                         Golang
int (*x)(int, int)  <-->  var x func(int, int) int  //x has the type "func (int,int) int" 

// 复合类型声明
C                       Golang

int *x[5];   <-->       var x [5]*int  //x is an array[5] of pointer to int
int (*x[5])(int, int)   类似于  var x [5]func(int, int) int   // x is an array[5] of "fun (int, int) int" 

特性

  1. Go语言支持多重赋值,在进行交换变量时候十分方便,而且go中全是这么书写
func swap(a,b int) {
    a,b = b,a
}
  1. 错误处理也使用了多重赋值,并且使用了匿名变量来充当占位符
    此示例还有函数的知识,函数可以预先定义返回变量,最后直接return即可
    函数也可以返回多个值,因此在接收返回值的使用需要使用多重赋值的方式,对于不想接受的返回值使用_来占位。
// 定义一个 DivideError 结构
type DivideError struct {
    dividee int
    divider int
}

// 实现 `error` 接口
func (de *DivideError) Error() string {
    strFormat := 
`
Cannot proceed, the divider is zero.
dividee: %d
divider: 0
`
    return fmt.Sprintf(strFormat, de.dividee)
}

// 定义 `int` 类型除法运算的函数
func Divide(varDividee int, varDivider int) (result int, errorMsg string) {
    if varDivider == 0 {
            dData := DivideError{
                    dividee: varDividee,
                    divider: varDivider,
            }
            errorMsg = dData.Error()
            return
    }
    return varDividee / varDivider, ""
}

func main() {
    // 正常情况
    if result, errorMsg := Divide(100, 10); errorMsg == "" {
            fmt.Println("100/10 = ", result)
    }
    // 当除数为零的时候会返回错误信息
    if _, errorMsg := Divide(100, 0); errorMsg != "" {
            fmt.Println("errorMsg is: ", errorMsg)
    }
}

Go语言全局变量

全局变量必须在函数体外声明,且必须是标准声明

var globalVal int = 0

var (
    GlobalValExt int = 1
    CountExt int = 2
    GlobalString string = "tencent"
)

全局变量只有首字母大写才能被外部源文件通过import “packkage”的方式调用,也就说globalVal只能在自身所在的源文件被调用。而批量声明的GlobalValExt、CountExt int、GlobalString可以被外部调用。

匿名变量

_

  • 不能作为右值
  • 匿名变量不占用内存空间,不会分配内存。匿名变量与匿名变量之间也不会因为多次声明而无法使用。
  • 接收函数多个返回值的时候可以用来忽略返回值

变量的生命周期

go语言中变量一般可以分为局部变量(包括参数列表、返回值)、全局变量。go还存在逃逸分析这一概念,编译阶段编译器会自动对变量进行分析,是将变量分配在栈还是堆上。

// 定义一个全局变量gVar
var gVar *int

// 这里x会发生逃逸,被分配到堆内存中
func f() {
    var x int
    x = 1
    gVar = &x
}

// 这里y在函数生命周期结束后就不再使用,因此y可以指向栈内存一段区域
func g() {
    y := new(int)
    *y = 1
}

// PS: 
// 栈内存分配速度极快,且不用专门的垃圾回收算法。
// 堆内存分配略慢,内存不足以分配一段连续空间时需要进行垃圾回收

func main(){
    f()
    g()
}

通过命令 go run -gcflags "-m -l" main.go来运行程序,可以打印出变量的逃逸分析情况。

-gcflags 参数是编译参数。其中 -m 表示进行内存分配分析,-l 表示避免程序内联,也就是避免进行程序优化

因此从以上代码可以看出,无论使用var还是new关键字来声明变量都不会影响编译器对变量分配方式的选择。

综上,go会自动完成内存的分配和释放,但为了能保证程序的高可用性,还是需要避免变量的逃逸,降低内存的消耗。

Go语言的常量

常量的初始化方式:

// 常量最基本的声明方式
const MAXLEN int = 10

// 常量只能通过内置函数或者unsafe.Sizeof()等函数来赋值,并且参数也要求是常量!
const MAXSIZE int = unsafe.Size(MAXLEN) 

iota常量生成器

const (
    a = iota
    b
    c
    d
    e
)

fmt.Println(a,b,c,d,e)
// 0 1 2 3 4 

const (
	i = 1 << iota
	j
	k
	l
	m
	n
)

// 它可以以类似的方式来为常量做初始化。
fmt.Println(i, j, k, l, m, n)
// 1 2 4 6 8 10

自定义枚举类型

go语言目前还没有基础的枚举类型,但可以使用常量来进行定义

type Chiep int

const (
	None Chiep = iota
	CPU
	GPU
)

// 实现chiep接口来实现从枚举类型到字符串的转换
func (c Chiep) String() string {
	switch c {
	case None:
		return "None"
	case CPU:
		return "CPU"
	case GPU:
		return "GPU"
	}
	return "N/A"
}


func main() {
    fmt.Printf("%s -> %d",CPU,CPU)
    // CPU -> 1
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值