一文详解Golang中的基础语法

2023-03-07 09:06:05

目录导包工程管理变量变量声明格式化输出基本数据类型强制类型转换接收键盘输入常量常量声明iota枚举运算符算术运算符赋值运算符关系运算符逻辑运算符条件语句if语句switch语句循环语句函数函数定...

目录
导包
工程管理
变量
变量声明
格式化输出
基本数据类型
强制类型转换
接收键盘输入
常量
常量声明
iota 枚举
运算符
算术运算符
赋值运算符
关系运算符
逻辑运算符
条件语句
if 语句
switch 语句
循环语句
函数
函数定义
参数列表
函数返回值
函数类型
匿名函数
递归函数

导包

示例:工程结构如下

一文详解Golang中的基础语法

GOPATH 设置为工程根目录(E:\GO_PROJECT)

test1.go

package package_test

import "fmt"

/*
定义函数
*/
func Func1() {
    fmt.Println("test1 func1")
}

test2.go

package package_test

import "fmt"

func Func2() {
    fmt.Println("test2 func2")
}

testmain.go

package main

import "dir1/dir2"  // 导入的是【目录名】

func main() {
    package_test.Func1()  // 调用的是【包名】
}

运行:

// 方式一
go bulid testmain.go  // 编译(生成可执行文件)
./ testmain  // 运行(可执行文件)

//方式二
go run testmain.go  // 编译+运行

导包结论:

一个 GO 程序中一定要有 main 包和 main 函数,这是 GO 程序执行的入口。

编译器会根据指定的相对路径去搜索包然后导入,这个相对路径是从 GOROOT 或 GOPATH(workspace)下的 src 下开始搜索:

GOROOT
项目 GOPATH
全局 GOPATH

golang 和 Java 的区别是,在 GO 中 import 的是目录,而不是包名;并且 GO 没有强制要求包名和目录名需要一致,即包和目录是两个不同的概念。

import 导入的是源文件所在的目录名,而不是定义的包名。

在代码中引用包内的成员时,使用定义的包名而不是目录名。

在习惯上将包名和目录名保证一致,但这并不是强制规定。

在同一级目录中,所有源文件只能使用相同的包名。

同一包名下的变量名、函数名等不能重复。

多个目录下的相同包名,彼此无关。

包中的成员(如函数)以名称⾸字母⼤⼩写,决定其访问权限:

⾸字母⼤写,可被包外访问(即public
⾸字母⼩写,仅包内成员可以访问(即private

工程管理

为了更好的管理项目中的文件,GO 要求将文件都要放在相应的目录中,具体规定了以下目录:

src 目录:以代码包的形式组织并保存 GO 源码文件(比如 .go 文件、.c 文件、.h 文件、.s 文件等)
pkg 目录:用于存放经由 go install 命令构建安装后的代码包(包含 GO 库源码文件)的 ".a" 归档文件。
bin 目录:与 pkg 目录类似,在通过 go install 命令完成安装后,保存由 GO 命令源javascript码文件生成的可执行文件。

以上目录称为工作区(Workspace),工作区其实就是一个对应于特定工程的目录。

src 目录用于包含所有的源代码,是 GO 命令行工具一个强制的规则;而 pkg 和 bin 则无需手动创建,GO 命令行工具在构建过程中会自动创建这些目录。

变量

变量声明

变量名必须以字母或下划线开头,后面可以跟任意数量的字母、数字或下划线。
变量的三种声明&初始化方式如下:
// 方式一:先声明(有默认值),后赋值
var a int
a = 10
var b, c string
b = "b"
c = "c"

// 方式二:声明+赋值
var a int = 10

// 方式三:自动推导类型(注意:这种方式只能在函数内使用)
a := 10
b, c := 11, 12
b, c = c, b  // 值交换

// 匿名变量
_, i, _, j = 1, 2, 3, 4

格式化输出

格式含义%%一个 % 字面量%b一个二进制整数值(基数为 2),或者是一个(高级的)用科学计数法表示的指数为 2 的浮点数%c字符型。可以把输入的数字按照 ASCII 码相应转换为对应的字符%d一个十进制数值(基数为 10)%f以标准记数法表示的浮点数或者复数值%o一个以八进制表示的数字(基数为8)%p以十六进制(基数为 16)表示的一个值的地址,前缀为 0x,字母使用小写的 a-f 表示%q使用 GO 语法以及必须时使用转义,以双引号括起来的字符串或者字节切片 []byte,或者是以单引号括起来的数字%s字符串。输出字符串中的字符直至字符串中的空字符(字符串以 '\0' 结尾,这个 '\0' 即空字符)%t以 true 或者 false 输出的布尔值%T使用 GO 语法输出的值的类型%x以十六进制表示的整型值(基数为十六),数字 a-f 使用小写表示%X以十六进制表示的整型值(基数为十六),数字 A-F 使用小写表示

基本数据类型

类型名称长度零值(默认值)说明bool布尔类型1false其值不为真即为假,不可以用数字代表 true 或 falsebyte字节型10uint8 的别名int, uint整型-0有符号 32 位或无符号 64 位int8整型10-128 ~ 127uint8整型100 ~ 255int16整型20-32768 ~ 32767uint16整型200 ~ 65535int32整型40-2147483648 到 2147483647rune整型40int32 的别名uint32整型400 到 4294967295(42 亿)int64整型80-9223372036854775808到 92233720368547758070uint64整型80到 18446744073709551615(1844 京)float32浮点型40.0小数位精确到 7 位float64浮点型80.0小数位精确到 15 位string字符串-""utf-8 字符串

值的字面量(literal)是指代码中值的文字表示。一个值可能存在多种字面量表示。

表示基本类型值的文本称为基本字面量。基本字面量也被称为字面量常量或未命名常量。

示例:

func main() {
    var ch byte = 97  // 声明字符类型
    fmt.Printf("ch=%c", ch)  //  输出 a
}

这里定义了 ch 是一个字符类型,赋值却是一个整数 97,打印的结果是小写字符 'a'。

原因是:计算机不能直接存储字符类型,只能转成数字存储,那为什么小写字符 'a' 对应的整数是 97 呢?因为计算机是根据 ASCII 码来存储的。

一文详解Golang中的基础语法

强制类型转换

package main

import "fmt"

func main() {

    chinese := 97
    math := 99
    english := 96

    fmt.Printf("总分是 %d,平均分(整数)是 %d, 平均分(浮点数)是 %f", chinese+math+english, (chinese+math+english)/3, float32(chinese+math+english)/3)
    // 总分是 292,平均分(整数)是 97, 平均分(浮点数)是 97.333336
}

注意:

GO 语言中不允许隐式转换,所有类型转换必须显式声明(强制转换),而且转换只能发生在两种相互兼容的类型之间

    var ch byte = 'c'
    // var a int = ch  // cannot use ch (type byte) as type int in assignment
    var b int = int(ch)  // 数据类型名(待转换的值)
int 转 float 强制转换:多小数
float 转 int 强制转换:丢精度

接收键盘输入

package main

import fmt

func main() {
    var age int
    fmt.Println("请输入年龄:")
    fmt.Scanf("%d", &age)  // 将接收的值赋给age变量
    fmt.Printf("age=%d", age)
}

常量

常量声明

func main() {
    // 变量:程序运行期间,值可以改变,声明使用var
    // 常量:程序运行期间,值不可以改变,声明使用const
    const a int = 11
    // a = 12  // error:常量不可以修改
    
    const b = 12 // 自动推导类型(常量不可以使用:=)
}

iota 枚举

iota 常量生成器:用于生成一组递增的整型常量,减去了每行都要写一遍初始化表达式的繁琐。

func main() {

    // 在一个 const 声明语句中,在第一个声明的常量所在的行,iota 将会被置为 0,然后在每一个有常量声明的行递增 1
    const (
        a = iota  // 0
        b = iota  // 1
        c = iota  // 2
    )

    const d = iota // iota 遇到const,会被置为 0

    // 可以只写一个iota
    const (
        e = iota  // 0
        f // 1
        g
    )

    // 同一行值一样
    const (
        h = iota  // 0
        i, j, k = iota, iota, iota  // 1
        l = iota  // 2
    )

}

运算符

算术运算符

运算符术语+加(既可以完成两个数字相加,又可以连接两个字符串)-减*乘/除%取模(取余)++后自增(GO 语言中没有前自增)--后自减(GO 语言中没有前自减)

赋值运算符

运算符说明示例=普通赋值c = a + b 将 a + b 表达式结果赋值给 c+=相加后再赋值c += a 等价于 c = c + a-=相减后再赋值c -= a 等价于 c = c - a*=相乘后再赋值c *= a 等价于 c = c * a/=相除后再赋值c /= a 等价于 c = c / a%=求余后再赋值c %= a 等价于 c = c % a

关系运算符

运算符术语示例结果==相等于4 == 3false!=不等于4 != 3true<小于4 < 3false>大于4 > 3true<=小于等于4 <= 3false>=大于等于4 >= 1true

逻辑运算符

运算符术语示例结果!非!a如果 a 为假,则 !a 为真
如果 a 为真,则 !a 为假&&与a && b如果 a 和 b 都为真,则结果为真,否则为假||或a || b如果 a 和 b 有一个为真,则结果为真,二者都为假时,结果为假

条件语句

if 语句

package main

import "fmt"

func main() {

    var score int
    fmt.Println("请输入成绩:")
    fmt.Scanf("%d", &score)

    // if 语句支持一个初始化语句+判断条件
    if good_score := 90; score >= good_score {
        fmt.Println("优秀")
    } else if soso_score := 60; score >= soso_score {
        fmt.Println("及格")
    } else {
        fmt.Println("需要努力")
    }
}

switch 语句

注意:case 后面默认自带 break,如果想执行完成某个 case 后继续执行后面的 case,可以使用 fallthrough 关键字。

func main() {

    bonus := 5000
    var score string
    finish := true
    fmt.Println("请输入年终评级:")
    switch fmt.Scanf("%s", &score); score {
    case "A":
        bonus += 1000
    case "B":
        bonus += 5000
    case "C":
    case "D":
        bonus -= 1000
    default:
        finish = false
        fmt.Println("输入有误,请输入正确的评级")
    }
    if finish {
        fmt.Printf("您的年终奖为:%d", bonus)
    }

}

循环语句

GO 中的 3 种循环方式:

package main

import "fmt"

func main() {

    // 第1种方式
    for i := 0; i < 5; i++ {
        fmt.Printf("i=%d\n", i)
    }

    // 第2种方式:类似while循环
    num := 1
    for num < 5 {
        fmt.Printf("num=%d\n", num)
        num++
    }

    // 第3种方式
    for {
        fmt.Println("死循环")
    }
}

函数

函数定义

函数就是将一堆代码进行封装,以便重用的一种机制。

func 函数名(){
    函数体
}

参数列表

import "fmt"

func MyFunc(a int, b int, args ...int) {  // 注意:不定长参数必须放在参数列表最后
    fmt.Println("定长参数为:", a, b)
    for i, data := range args {  // 若不需要编号,则可使用 for _, data := range args
        fmt.Println("编号为:", i)
        fmt.Println("数据为:", data)
    }
}

func main() {
    MyFunc(1, 2, 3, 4, 5)
}

打印结果:

定长参数为: 1 2
编号为: 0
数据为: 3
编号为: 1
数据为: 4
编号为: 2
数据为: 5

函数返回值

// 定义返回值类型
func Add(a int, b int) int {
    return a + b
}

// 给返回值命名
func Sub(a int, b int) (sub int) {
    sub = a - b
    return sub  // 也可以只写 return
}

// 返回多个值
func Sub(a, b, c int) {
    a, b, c = 1, 2, 3
    return a, b, c  // 也可以只写 return
}

函数类型

在 GO 语言中还有另外一种定义使用函数的方式,就是函数类型。

所谓的函数类型,就是将函数作为一种类型可以用来定义变量,基本使用如下:

func Test(a, b int) int {
    return a + b
}

// 定义函数类型:即需要传递两个整型参数,有一个整型返回值的函数类型
type FuncType func(a int, b int) int  // type关键字后面跟着类型的名字(FunType)

func main() {
    var result FuncType  // 类型是FuncType类型,即函数类型
    result = Test
    s := result(1, 2)
    fmt.Printf("s=%d", s)
}

匿名函数

所谓匿名函数就是没有名字的函数。匿名函数最主要的功能就是实现了闭包。

package main

import "fmt"

func main() {
    num := 9

    // 使用方式一:定义匿名函数并赋值给变量
    f1 := func() {
        // 在匿名函数中可以直接访问main()中定义的局部变量
        // 并且在匿名函数中对变量的值进行了修改,最终会影响到整个main()函数中定义的变量值
        num++
        fmt.Println("匿名函数:", num)
    }
    f1()                        // 10
    fmt.Println("main函数:", num) // 10

    // 使用方式二:通过函数类型
    type FuncType func() // 没有参数,没有返回值
    var f2 FuncType = f1
    f2()

    // 使用方式三:直接调用
    func(a, b int) {
        fmt.Println("a + b =", a+b)
    }(3, 6)

    // 有参有返回值的匿名函数
    min, max := func(a, b int) (min, max int) {
        if a > b {
            return b, a
        } else {
            return a, b
        }
    }(12, 13)
    fmt.Printf("min=%d, max=%d\n", min, max)
}

递归函数

示例:阶乘

func Test(num int) int {
    if num == 1 {
        return 1
    }
    return num * Test(num-1)
}

func main() {
    var num int
    fmt.Println("请输入需要阶乘的数:")
    fmt.Scanf("%d", &num)
    fmt.Printf("%d的阶乘结果为:%d", num, Test(num))
}

 以上就是一文详解Golang中的基础语法的详细内容,更多关于Golang基础语法的资料请关注我们其它相关文章!