Go 语言基础语法 (二) | 豆包MarsCode AI 刷题

54 阅读8分钟

给大家推荐一款曾经风靡一时的休闲娱乐小游戏——2048

2048.png

只要我们下载安装了Go,就可在开发环境下的终端内直接输入下列命令,就可启动游戏:

go run github.com/hajimehoshi/ebiten/v2/examples/2048@latest

回归正题 让我们继续来回顾GO语言基础语法

1. Go 变量

1.1 变量是什么?

变量来源于数学,是计算机语言中能储存计算结果或能表示值的抽象概念,变量可以通过变量名访问,但不同的变量保存的 数据类型 可能会不一样。

1.2 变量的定义

声明变量的一般形式是使用var关键字:var identifier type

  • var: 关键字,表示声明变量
  • identifier: 变量名字
  • Type:数据类型,这是一种抽象表示,仅作文档说明,代表任意类型

当然也可以,一次声明多个变量,如:var identifier1, identifier2 type

package main
import "fmt"
func main() {
    var a string = "Runoob"
    fmt.Println(a)

    var b, c int = 1, 2
    fmt.Println(b, c)
}

/*以上实例输出结果为:1 2 */

提示:
Go语言中的变量需要 声明后才能使用同一作用域内不支持重复声明。 并且Go语言的变量 声明后必须使用

1.3 变量名的命名规则

Go 语言变量名由字母、数字、下划线组成,其中首个字符不能为数字。

所谓 变量名 就是程序中预先分配好的 固定大小的内存区域,在 Go 中可以想象它是一个 抽屉,将数据内容存放在其中。而变量名的内存区域的大小则是由它的 数据类型 所确定。

补充:

  • 名称只能包含字母 数字 字符和 下划线(a-zA-Z0-9_)
  • 名称是 区分大小写(ageAge 和 AGE 是三个不同的变量)
  • 名称是 没有长度限制
  • 名称中 不能包含空格
  • 名称 不能是任何 Go关键字

因为有些 变量名被编程语言赋予了特殊的含义,它们作为其语言的重要组成部分被称为 关键字 或 保留字。这些名字是不能用于变量的命名。
Go语言中有 25关键字 :

1.breakdefaultfuncinterfaceselect
2.casedefergomapstruct
3.chanelsegotopackageswitch
4.constfallthroughifrangetype
5.continueforimportreturnvar

此外,Go 语言中还有 37保留字 :

常量: true false iota nil

数据类型: int int8 int16 int32 int64 uint uint8 uint16 uint32 uint64 uintptr float32 float64

complex128 complex64 bool byte rune string error

内置函数: make len cap new append copy close delete complex real imag panic recover

package main

import "fmt"

func main() {
     var name string
     var age int
     var _sys int
}

除此之外,包含多个单词的变量名可能难以阅读,使用一些技巧来提高可读性。

  • 驼峰命名法——除了第一个单词,每个单词都以大写字母开头 : myVariavleName := "John"
  • 帕斯卡命名法——每个单词都以大写字母开头 : MyVariableName := "John"
  • 蛇形命名法——每个单词由一个下划线字符分隔my_variable_name := "John"

多变量声明 :使用一个 var 关键字,把一些变量写在一个括号()

//类型相同多个变量, 非全局变量
var vname1, vname2, vname3 type
vname1, vname2, vname3 = v1, v2, v3
var vname1, vname2, vname3 = v1, v2, v3 // 和 python 很像,不需要显示声明类型,自动推断 vname1, vname2, vname3 := v1, v2, v3 // 出现在 := 左侧的变量不应该是已经被声明过的,否则会导致编译错误
// 这种因式分解关键字的写法一般用于声明全局变量
var (
vname1 v_type1
vname2 v_type2
)

package main
import "fmt"

var x, y int
var (  // 这种因式分解关键字的写法一般用于声明全局变量
    a int
    b bool
)

var c, d int = 1, 2
var e, f = 123, "hello"

//这种不带声明格式的只能在函数体中出现
//g, h := 123, "hello"

func main(){
    g, h := 123, "hello"
    fmt.Println(x, y, a, b, c, d, e, f, g, h)
}

/*以上实例执行结果为:0 0 0 false 1 2 123 hello 123 hello */

1.4 变量的初始化

第一种,指定变量类型,如果没有初始化,则变量默认为零值。

零值就是变量没有做初始化时系统默认设置的值。

Go语言在声明变量的时候,会自动对变量对应的内存区域进行初始化操作。每个变量会被初始化成其类型的默认值,例如:

  • 整型和浮点型变量的默认值为 0
  • 字符串变量的默认值为空字符串 ""
  • 布尔型变量默认为 false
  • 切片、函数、指针变量的默认为 nil

初始化 标准语法 如下: var identifier Type - value

package main

func main() {
      // 变量的初始化
      var name string = "杜宇鹏"
      var age int = 28
}

第二种,根据值自行判定变量类型。

如果提供初始值,编译器可以自动从初始值中获取类型信息

package main

func main() {
    var name = "杜宇鹏"
    var age = 28
    var ok = true
}

也可以初始化多个变量,让编译器进行类型推导,一次初始化多个变量

package main

func main() {
        /*多变量初始化*/
        var name, age, ok = "杜宇鹏", 28, true
}

第三种,如果变量已经使用 var 声明过了,再使用:=声明变量,就产生编译错误。

格式: v_name := value

在 函数内部,可以使用 := 运算符对变量进行声明和初始化

package main

func main() {
        /*短变量声明*/
        name := "杜宇鹏"
        age := 28
        ok := true
}

该声明,必须在函数内部。并且必须提供初始值。不提供初始值是不可能进行变量声明的

但当 var intVal int intVal :=1 这时候会产生编译错误,因为 intVal 已经声明,不需要重新声明

直接使用下列语句即可: intVal := 1此时不会产生编译错误,因为有声明新的变量,因为 := 是一个声明语句。

intVal := 1 相等于:
var intVal int
intVal =1

第四种,匿名变量。

如果我们需要接收到多个值,有一些值使用不到,可以使用 下划线 _ 表示变量名称,这种变量叫做 匿名变量

package main

import "fmt"

func getNameAndAge() (string, int) {
        return "杜宇鹏", 30
}

func main() {
        /* 使用匿名变量忽略值 */
        name, _ := getNameAndAge()
        fmt.Printf("name: %s\n", name)
}

但后续我们也无法使用 _ 获取值,它就像粉碎机一样,将数据毁灭了

2. Go 常量

2.1 常量是什么?

常量是一个简单值的标识符,在程序运行时,不会被修改的量。

常量中的数据类型只可以是布尔型、数字型(整数型、浮点型和复数)和字符串型。 可以使用 const 关键字。

2.2 常量的定义

const 关键字 将变量声明为 只读意味着它是 不可更改且只读的。语法格式如下:

const CONSTNAME Type = value

注意,常量的值必须在声明时赋初始值,声明完成之后不允许修改。

Go 常量的声明与变量非常相似。区别在于声明常量使用 const 关键字,并且在声明时就必须初始化

  • 显式类型定义: const b string = "abc"

  • 隐式类型定义: const b = "abc" (编译器可以根据变量的值来推断其类型)

多个相同类型的声明可以简写为: const c_name1, c_name2 = value1, value2

package main

import "fmt"

func main() {
   const LENGTH int = 10
   const WIDTH int = 5   
   var area int
   const a, b, c = 1, false, "str" //多重赋值

   area = LENGTH * WIDTH
   fmt.Printf("面积为 : %d", area)
   println()
   println(a, b, c)   
}

/* 以上实例运行结果为:
面积为 : 50
1 false str
*/ 

常量还可以用作枚举:

const (
Unknown = 0
Female = 1
Male = 2
)
数字 0、1 和 2 分别代表未知性别、女性和男性。

const 同时声明多个常量时,如果省略了值则表示和上面一行的值相同

package main

import "fmt"

const (
        k = 1 // 开始值
        m     // 默认为上一项 k 的值 1
        g
        t = 2 // 新的值
        p     // 默认为上一项 t 的值 2
        q
)

func main() {
        fmt.Println(k, m, g, t, p, q) // 1 1 1 2 2 2
}

常量可以用len(), cap(), unsafe.Sizeof()函数计算表达式的值。常量表达式中,函数必须是内置函数,否则编译不过:

package main

import "unsafe"
const (
    a = "abc"
    b = len(a)
    c = unsafe.Sizeof(a)
)

func main(){
    println(a, b, c)
}

/* 以上实例运行结果为:abc 3 16 */

2.3 iota

iota,特殊常量,可以认为是一个可以被编译器修改的常量
iota 在 const关键字出现时将被重置为 0(const 内部的第一行之前),const 中每新增一行常量声明将使 iota 计数一次(iota 可理解为 const 语句块中的行索引)。

iota 可以被用作枚举值:
const (
a = iota
b = iota
c= iota
)

第一个 iota 等于 0,每当 iota 在新的一行被使用时,它的值都会自动加 1;所以 a=0, b=1, c=2 可以简写为如下形式:
const (
a = iota
b
c
)

iota 用法

package main

import "fmt"

func main() {
    const (
            a = iota   //0
            b          //1
            c          //2
            d = "ha"   //独立值,iota += 1
            e          //"ha"   iota += 1
            f = 100    //iota +=1
            g          //100  iota +=1
            h = iota   //7,恢复计数
            i          //8
    )
    fmt.Println(a,b,c,d,e,f,g,h,i)
}

/*以上实例运行结果为:0 1 2 ha ha 100 100 7 8 */

看个有趣的的 iota 实例:

 package main

import "fmt"
const (
    i=1<<iota
    j=3<<iota
    k
    l
)

func main() {
    fmt.Println("i=",i)
    fmt.Println("j=",j)
    fmt.Println("k=",k)
    fmt.Println("l=",l)
}

/* 以上实例运行结果为:i= 1 j= 6 k= 12 l= 24 */

iota 表示从 0 开始自动加 1,所以 i=1<<0, j=3<<1( <<  表示左移的意思),即:i=1, j=6,这没问题,关键在 k 和 l,从输出结果看 k=3<<2,l=3<<3。

简单表述:

  • i=1:左移 0 位,不变仍为 1。
  • j=3:左移 1 位,变为二进制 110,即 6。
  • k=3:左移 2 位,变为二进制 1100,即 12。
  • l=3:左移 3 位,变为二进制 11000,即 24。

注意: <<n == *(2^n)