Go语言学习笔记-03变量

85 阅读7分钟

Go语言学习笔记-03变量

数据类型

  1. 布尔型,bool

  2. 无符号整形,uint,uint8,unit16,uint32,uint64

  3. 有符号整形,int,int8,int16,int32,int64

  4. 浮点型,float32,float64

  5. 复数型,complex64,complex128

  6. 字符串,string,表示Unicode字符序列

  7. 其他数字类型

    byte,uint8的别名,表示单字节字符

    rune,int32的别名,表示一个Unicode码点

    uintptr,大到足够保存任何指针类型的整形类型

  8. 派生类型

    数组类型,[n]T,表示元素类型为 T 的 n 个元素的数组的类型

    切片类型,[]T,表示元素类型为 T 的可变长度数组的类型

    map类型,键值对的无序集合,类似于其他语言中的字典或哈希表

    结构化类型(struct),由多个字段组成的自定义数据类型

    channel类型,用于在goroutine之间进行同步通信

    指针类型(Pointer),*T

    函数类型,func

    接口类型(interface),表示实现特定方法的类型的类型

变量的声明

go是静态类型语言,声明变量时需要确定好变量的数据类型,不能在同一作用域中声明同名变量

声明有以下几种方式

  1. 仅声明不赋值
var 变量名 数据类型
  1. 声明同时赋值
var 变量名 数据类型 = 值
  1. 声明时缺省变量类型。

    go编译器会根据右边值,自动推导默认类型,若默认类型不是想要的类型,则可以显式类型转换

var 变量名 = 值
var 变量名 = 值
var 变量名 = 数据类型(值)
  1. 同时申明多个变量
var (
变量名1 数据类型1
变量名2 数据类型2
)

var (
变量名1 数据类型1 = 值1
变量名2 数据类型2 = 值2
)
  1. 同一行同时声明多个变量
// 数据类型一致
var 变量名1, 变量名2 数据类型
var 变量名1, 变量名2 数据类型 = 值1, 值2

// 数据类型不一致,采用缺省数据类型方式
var 变量名1, 变量名2 = 值1, 值2
  1. 短变量声明,相当于声明一个变量并赋值

    只能在函数体中使用

    go编译器会根据右边的值,自动推导默认类型,若默认类型不是想要的类型,则可以显式类型转换

变量名 := 值
变量名 := 数据类型(值)
变量名1, 变量名2 := 值1, 值2

变量的赋值

go语言中,类型不同的变量不能赋值给对方,如int32的变量,不能直接赋值给int的变量

空白标识符

空白标识符也称为匿名占位符,使用_表示

在 Go 语言中, 不允许声明未使用的变量或导入语句,这时可以使用空白标识符忽略掉

全局变量

在函数体外声明的变量是全局变量,也称为包级变量

只能使用var方式申明,无法使用短变量声明方式

package main

// 全局变量
var 变量名 数据类型
var 变量名 = 值
var (
   变量名1 = 值1
   变量名2 = 值2
)

func main() {
}

代码示例

ch03/main.go

package main

// 全局变量声明
var globalA1 int
var globalB1 = 1

var (
   globalC1 = 1
   globalC2 = 1
)

func main() {
   // 指定变量类型,没有初始化
   var a1 int

   // 声明并初始化
   var b1 int = 1

   // 变量声明块,批量声明多个变量
   var (
      c1 int    = 128
      c2 int8   = 6
      c3 string = "hello"
      c4 rune   = 'A'
      c5 bool   = true
   )

   // 在一行同时声明多个变量
   var d1, d2, d3 int = 1, 2, 3

   // 在一行同时声明多个变量,类型不一致
   var (
      e1, e2, e3 = "e1", 2, 3.0
   )

   // 省略类型信息的声明,类型为默认类型
   var f1 = 1          // int
   var f1_1 = int32(1) // int32
   var f2 = 1.1        // float64
   var f3 = 'c'        // int32
   var f4 = "d"        // string
   var f5 = true       // bool

   // 短变量声明,申明并赋值,只能在函数体中使用
   // 相当于
   // var a int
   // a = 12
   g1 := 12
   g2 := 'A'
   g3 := "hello"
   g4, g5, g6 := 12, 'A', "hello"

   // 使用空白标识符_忽略掉未使用的变量
   _ = globalA1
   _ = globalB1
   _, _ = globalC1, globalC2
   _ = a1
   _ = b1
   _, _, _, _, _ = c1, c2, c3, c4, c5
   _, _, _ = d1, d2, d3
   _, _, _ = e1, e2, e3
   _, _, _, _, _, _ = f1, f1_1, f2, f3, f4, f5
   _, _, _, _, _, _ = g1, g2, g3, g4, g5, g6

   // 当有新变量申明时,需要使用短变量声明方式
   _, h7 := 0, 0
   _ = h7
}

fmt包

fmt包主要用于向外输出内容和获取输入内容

Println

打印多个值并换行

ch03/fmt/main.go

package main

// 导入fmt包的包路径
import "fmt"

func main() {
   fmt.Println(1, 2, 3)
   fmt.Println(4, 5, 6)
}

上述代码输出

1,2,3
4,5,6

Printf

格式化输出,通过不同的占位符控制输出格式

常用占位符

占位符说明
%v值的默认格式表示
%+v类似%v,但输出结构体时会添加字段名
%#v值的Go语法表示
%T打印值的类型
%%百分号
%d打印整数
%c打印对应unicode码值
%s打印字符串或[]byte
%f打印浮点数
%t打印布尔类型

ch03/fmt/main.go

package main

import "fmt"

func main() {
   var a1 = 1
   var a2 = 'a'
   var a3 = true
   fmt.Printf("%d %c %t", a1, a2, a3)
}

上述代码输出

1 a true

默认类型

缺省指定类型时,go会根据右值自动推导其数据类型

类型备注
整数int当数值不在int所能表示的范围内,则需要显式指定数据类型
浮点数float64
字符runeint32的别名,与int32等价
字符串string
true,falsebool

ch03/defaulttype/main.go

package main

import "fmt"

func main() {
   var a = 1
   var b = 1.1
   var c = 'a'
   var d = "abc"
   var e = true

   fmt.Printf("变量a的类型为%T\n", a)
   fmt.Printf("变量b的类型为%T\n", b)
   fmt.Printf("变量c的类型为%T\n", c)
   fmt.Printf("变量d的类型为%T\n", d)
   fmt.Printf("变量e的类型为%T\n", e)
}

上述代码输出

变量a的类型为int
变量b的类型为float64
变量c的类型为int32  
变量d的类型为string 
变量e的类型为bool

零值

当只声明不赋值时,不同数据类型的变量会赋予其对应的零值

零值使得变量可以开箱即用,无需显示初始化,即零值可用

内置原生类型默认值零值是否可用
所有整形类型0
浮点类型0.0
布尔类型false
字符串类型""
指针、接口、切片、channel、map和函数类型nil
struct各字段对应类型的零值看具体字段的类型
数组填充对应类型的零值

例子

ch03/zerovalue/main.go

package main

import "fmt"

func main() {
   var var1 int
   var var2 float32
   var var3 bool
   var var4 string
   var var5 byte
   var var6 [5]int
   var var7 chan int
   var var8 map[string]int
   var var9 []int
   var var10 func() int

   // 注意有些是用%v,有些是用%#v

   fmt.Printf("int的零值为%v\n", var1)
   fmt.Printf("float32的零值为%v\n", var2)
   fmt.Printf("bool的零值为%v\n", var3)
   fmt.Printf("string的零值为%#v\n", var4)
   fmt.Printf("byte的零值为%v\n", var5)
   fmt.Printf("[5]int的零值为%v\n", var6)

   fmt.Printf("[]int的零值为%#v\n", var9)
   fmt.Printf("chan int的零值为%#v\n", var7)
   fmt.Printf("map的零值为%#v\n", var8)
   fmt.Printf("func() int的零值为%#v\n", var10)
}

上述代码输出

int的零值为0
float32的零值为0                   
bool的零值为false                  
string的零值为""                   
byte的零值为0                      
[5]int的零值为[0 0 0 0 0]          
[]int的零值为[]int(nil)            
chan int的零值为(chan int)(nil)    
map的零值为map[string]int(nil)     
func() int的零值为(func() int)(nil)

可以看出默认值为nil的数据类型类型不是单纯的nil,而是带有具体数据类型的nil,它们是不等价的

作用域

在go语言中,{}包括的内容称之为一个代码块,可以嵌套,外层代码块的作用域包括所有内层代码块,换言之,外层代码块的变量可以在内层代码块内使用,在内层代码块定义与外层代码块同名的变量,会遮蔽外层代码块的同名变量,这种现象称之为变量遮蔽

除了有显示代码块,还有隐式代码块,包括ifforswitch

例子

ch03/variablemasking/main.go

package main

import "fmt"

var a = 1

func main() {
   {
      // 遮蔽包级变量a
      a := 2
      fmt.Println(a) // 2
   }

   if a := 3; a == 3 {
      fmt.Println(a) // 3
   }

   // 等价于上面的if语句,外层的{}就是隐藏的代码块
   {
      a := 3
      if a == 3 {
         fmt.Println(a) // 3
      }
   }

   // 都不影响包级变量a
   fmt.Println(a) // 1
}

笔记地址

github:github.com/xianyuyixia…

交流学习

微信号:xianyuyixia

wx_qrcode_258.jpg

微信公众号:闲渔一下

wx_platform.jpg

开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 2 天,点击查看活动详情