Logo
活死人の行知路

Go语言基础(一):变量、常量的定义与使用


📅 | 📝 848 字
#go #programming

Go 是一门静态强类型语言,变量必须先声明(或定义)才能使用,而且类型一旦确定不可改变。

1单变量声明的 3 种方式

1.1标准形式(var关键字+显式类型)

语法:var 变量名称 类型 = 表达式

var name string = "Tom"
var age int = 18
var isMarried bool = false
  • 可以写在函数内外(函数外就是包级变量)
  • 不赋值时自动获得零值(下面会详细讲)

1.2类型推断(var+自动推断)

语法:var 变量名称 = 表达式

编译器根据初始值自动推断类型,写法更简洁:

var name = "Tom"      // 推断为 string
var age = 18          // 推断为 int
var height = 1.88     // 推断为 float64
var isMarried = true  // 推断为 bool

1.3简短声明(:=)——最常用!

只能在函数内部使用,Go 独有的语法糖:

func main() {
    name := "Tom"      // 自动推断为 string
    age := 28          // 自动推断为 int
    score := 99.5      // 自动推断为 float64
}

重要规则:

  • := 左侧至少要有一个新变量
  • 同一个作用域内不能对已存在的变量再次使用 :=

错误示例:

func main() {
    x := 100
    // x := 200    // 编译错误!no new variables on left side of :=
    x = 200        // 正确,这是赋值,不是重新声明
}

正确示例(至少有一个新变量):

func main() {
    x := 100
    x, y := 200, "abc"   // x 是已存在变量,y 是新变量 → 合法
    fmt.Println(x, y)    // 200 abc
}

2多变量声明的 4 种方式

2.1一次声明多个变量(同类型)

var a, b, c int
var name1, name2, name3 string = "张三", "李四", "王五"

2.2一次声明多个变量(不同类型)

var name, age, isStudent = "Lucy", 20, true

2.3并行赋值(最常见)

var width, height = 100, 200
width, height = 300, 400      // 同时赋值
width, height = height, width // 不用临时变量就能交换

2.4变量组声明(推荐用于包级变量,当然函数内也能使用)

var (
	appName  string  = "GoWeb"
	version  string  = "1.0.0"
	debug    bool    = true
	maxRetry int     = 5
	pi       float64 = 3.14159
)

3Go的零值(默认值)机制

在Go语⾔中,每种类型都有相应的默认值,我们将其称为零值(zero value)。 Go不会出现“未初始化变量”这种运行时错误,所有变量声明后都会自动获得对应类型的零值:

类型零值
int / float0
boolfalse
string""(空字符串)
pointernil
slice/map/channil
struct所有字段都是零值
var a int
var b string
var c bool
var d *int
fmt.Printf("%d %q %t %v\n", a, b, c, d) // 0 "" false <nil>

4匿名变量“_”

在多返回值函数中经常只关心部分返回值,用 _ 丢弃不需要的值:

func getUser() (string, int, bool) {
    return "Tom", 18, true
}

func main() {
    name, _, isVip := getUser()   // 只关心名字和是否VIP
    _, age, _ := getUser()        // 只关心年龄
    fmt.Println(name, age, isVip)
}

遍历时同理:

for _, item := range list {
}

Python 程序员会感觉非常亲切,和 for _, item in enumerate(arr) 完全一样!

5变量命名规范与注意事项(必背)

规则示例说明
只能包含字母、数字、下划线user_name, age2
必须以字母或下划线开头_temp, Name不能以数字开头
区分大小写age ≠ Age
不能是关键字var, func, package 等Go 一共 25 个关键字
建议使用驼峰命名法userName, maxRetryCount不要用下划线
见名知意,越短越好i, j, k(循环索引)短变量只在小作用域使用
首字母大写即为导出AppVersion小写则包外不可见

6常见编译错误及解决办法

// 错误1:变量声明了没使用
var temp int    // 编译报错:temp declared and not used

// 错误2:重复使用 := 声明已存在变量
x := 10
x := 20         // 编译错误:no new variables on left side of :=

// 错误3:函数外使用 :=
package main

name := "global"  // 编译错误!只能在函数内部使用

7变量完整示例代码

package main

import "fmt"

// 包级变量(推荐使用 var() 方式)
var (
    AppName    = "GoStudy"
    Version    = "1.0.0"
    DebugMode  = true
)

func main() {
    // 1. 标准声明
    var name string = "Tom"
    var age int = 28

    // 2. 类型推断
    var city = "Beijing"

    // 3. 简短声明(最常用)
    score := 99.5
    isLogin := true

    // 4. 多变量声明
    x, y, z := 10, 20, 30

    // 5. 匿名变量
    username, _, vip := getUserInfo()

    fmt.Printf("欢迎来到 %s v%s\n", AppName, Version)
    fmt.Println(name, age, city, score, isLogin)
    fmt.Println(x, y, z)
    fmt.Println("用户:", username, "VIP:", vip)
}

func getUserInfo() (string, int, bool) {
    return "Jerry", 35, true
}

运行结果:

欢迎来到 GoStudy v1.0.0
Tom 28 Beijing 99.5 true
10 20 30
用户: Jerry VIP: true

8变量小结(背会这5点就够了)

  1. 函数内最常用 变量名 := 值
  2. 函数外只能用 var(推荐用 var() 批量声明)
  3. 声明了必须使用,否则编译不通过
  4. 同一个作用域内,:= 左侧至少有一个新变量
  5. 不关心的返回值用 _ 丢弃

9常量声明

常量用 const 声明,值在编译期确定,运行期间不能修改。

const LENGTH int = 10             // 显式类型
const b = "abc"                   // 隐式类型,自动推断
const a, c, d = 1, false, "str"   // 多重赋值

常量的类型只能是布尔型、数字型(整数/浮点/复数)、字符串型,数组、切片、map、struct、函数都不行。

10常量组

const (
	appName  string = "GoWeb"
	version         = "1.0.0"
	maxRetry int    = 5
)

10.1省略类型和值 → 与上一行完全相同

const (
	x int = 16
	y          // 16,int
	s = "abc"
	z          // "abc",string
)

y、z 既没写类型也没写值,直接继承上一行的类型和值。

10.2常量组内不能重名

const (
	unknown = 0
	male    = 1
	female  = 2
	male    = 3   // 编译错误:'male' redeclared in this block
)

10.3常量必须赋值

const j string 不能通过编译,常量没有“只声明不赋值”这种写法。

11iota

iota 是常量计数器,只能用在 const 块里:每个 const 块开始时归零,每换一行加 1。

const (
	a = iota // 0
	b        // 1
	c        // 2
)

b、c 没写 = iota,但继承了上一行的表达式,等价于 b = iota、c = iota。

11.1每个 const 关键字都是新的一轮

const a = iota // 0
const (
	b = iota   // 0  ← 重新从 0 开始
	c          // 1
)

11.2中断后不会自动恢复

const (
	a    = iota       // 0
	b                 // 1
	c                 // 2
	d    = "ha"       // "ha"  iota = 3
	e                 // "ha"  iota = 4
	f    = 100        // 100   iota = 5
	g                 // 100   iota = 6
	h, i = iota, iota // 7, 7
	j    = iota       // 8
)

d、e 的值是 "ha",f、g 的值是 100,但行号一直在走,iota 并没有停。想恢复计数,必须显式写 = iota(比如 j)。

11.3iota 可以参与运算

const (
	A1 = (iota + 1) * 100 // 100
	B1                    // 200
	C1                    // 300
	D1 = 10               // 10
	E1 = "hello"          // hello
	F1                    // hello
	G1 = iota             // 6
)

11.4用 iota 做枚举

Go 没有 enum,用常量组 + iota 代替:

const (
	Unknown = iota // 0
	Female         // 1
	Male           // 2
)

12常量与变量的区别

变量常量
声明方式var x int / x := 1const x = 1
能否修改能不能
声明后未使用编译报错不报错
声明不赋值可以,取零值不可以
值何时确定运行时编译期

另外几点:

  • 常量不能取地址——数字常量不分配存储空间,没有内存地址
  • 常量的值必须在编译期就能算出来,const t = time.Now() 编译不过
  • 同一常量组内名字不能重复

13常量小结

  1. 常量用 const 声明,值不可修改,类型只能是布尔、数字、字符串
  2. 常量组中某一行省略类型和值,就继承上一行
  3. iota 在每个 const 块里从 0 开始,每行加 1,中断后要显式写 = iota 才能恢复
  4. Go 没有枚举类型,用常量组 + iota 模拟
  5. 常量声明了不用不会报错,变量会