Go基础语法
Go语言以“包”作为管理单位,每个 Go 源文件必须声明它所属的包,所以我们会看到每个 Go 源文件的开头都是一个 package 声明
package main // 声明 main 包,main 包是 Go 语言程序的入口包,一个 Go 语言程序必须有且仅有一个 main 包。如果一个程序没有 main 包,那么编译时将会出错,无法生成可执行文件。
import "fmt" // 导入 fmt 包,导入的包中不能含有代码中没有使用到的包,否则Go编译器会报编译错误
func main() { // 声明 main 主函数,main 函数只能声明在 main 包中,不能声明在其他包中,并且,一个 main 包中也必须有且仅有一个 main 函数。Go语言函数的左大括号{必须和函数名称在同一行,否则会报错。
fmt.Println("Hello World!") // 打印 Hello World!
}
Go 语言基本数据类型
- 布尔型,默认为 false
bool
布尔型的值只可以是 true 或者 false
- 字符串类型,默认值为空字符串,使用双引号或反引号定义。字符串是一种值类型,且值不可变,即创建某个文本后将无法再次修改这个文本的内容
string
编码统一为 UTF-8 编码标识 Unicode 文本
整型,默认值为0
uint8
:无符号8位整型(0 - 255)uint16
:无符号16位整型(0 - 65535)uint32
:无符号32位整型(0 - 4294967295)uint64
:无符号64位整型(0 - 18446744073709551615)int8
:有符号8位整型(-128 ~ 127)int16
:有符号16位整型(-32768 ~ 32767)int32
:有符号32位整型(-2147483648 ~ 2147483647)int64
:有符号64位整型(-9223372036854775808 ~ 9223372036854775807)uintptr
:无符号整型,用于存放一个指针int
:有符号32位或64位uint
:无符号32位或64位byte
:类似 uint8rune
:类似 int32
浮点型,默认为0,声明一个没有指定数据类型的浮点数时,默认为float64类型
float32
:32位浮点数float64
:64位浮点数complex64
:32位实数和虚数complex128
:64位实数和虚数
大多数情况下,我们只需要 int 一种整型即可,它可以用于循环计数器(for 循环中控制循环次数的变量)、数组和切片的索引,以及任何通用目的的整型运算符,通常 int 类型的处理速度也是最快的。
byte 和 rune 可以表示字符类型
var b byte = 'a'
fmt.Println(b) // 97
Go语言中不允许将布尔型强制转换为整型,编译会报错
var n bool
fmt.Println(int(n))
// cannot convert n (type bool) to type int
变量的声明
使用 var 关键字(函数内外都可使用)
1. var a, b int
2. var a, b string = "hello", "world" // 字符串不能用单引号,可以不提供变量类型
3. var (
a int,
b string,
c bool = true,
d = "hi"
)
4. str := `this is another
string`
使用 := 方式声明(仅函数内部可用)
使用 := 声明变量不能提供数据类型
1. a := 1
2. a, b := 2, "hi" // 同时声明并赋值多个变量
Go语言中没有隐式转换,只能强制转换,const 定义常量没有指定数据类型时可以隐式的转换数据类型
package main
import "fmt"
func sum(a float32, b float32) float32{
return a + b
}
func main(){
// var m, n = 1.1, 2 // 报错
const m, n = 1.1, 2 // 正常
fmt.Println(sum(m, n))
}
常量
常量使用关键字 const 定义,用于存储不会改变的数据。
存储在常量中的数据类型只可以是布尔型、数字型(整数型、浮点型和复数)和字符串型。
常量的定义格式:const identifier [type] = value,例如:const Pi = 3.14159
在 Go 语言中,你可以省略类型说明符 [type],因为编译器可以根据变量的值来推断其类型。
- 显式类型定义:
const b string = "abc"
- 隐式类型定义:
const b = "abc"
数字型的常量是没有大小和符号的,并且可以使用任何精度而不会导致溢出
并行赋值
const beef, two, c = "eat", 2, "veg"
const Monday, Tuesday, Wednesday, Thursday, Friday, Saturday = 1, 2, 3, 4, 5, 6
const (
Monday, Tuesday, Wednesday = 1, 2, 3
Thursday, Friday, Saturday = 4, 5, 6
)
指针
每个变量在运行时都拥有一个地址,这个地址代表变量在内存中的位置。Go语言中使用在变量名前面添加&
操作符(前缀)来获取变量的内存地址(取地址操作)
package main
import "fmt"
func main(){
str := "指针"
fmt.Println(&str) // 0xc0000501f0
fmt.Printf("%T", &str) // *string
}
当使用&
操作符对普通变量进行取地址操作并得到变量的指针后,可以对指针使用*
操作符,也就是指针取值
package main
import "fmt"
func main(){
str := "PHP is the best language in the world!"
ptr := &str
value := *ptr
// 打印ptr的类型
fmt.Printf("ptr type: %T\n", ptr) // ptr type: *string
// 打印ptr的指针地址
fmt.Printf("address: %p\n", ptr) // address: 0xc0000661e0
// 取值后的类型
fmt.Printf("value type: %T\n", value) // value type: string
// 指针取值后就是指向变量的值
fmt.Printf("value: %s\n", value) //value: PHP is the best language in the world!
}
*
操作符的根本意义就是操作指针指向的变量。当操作在右值时,就是获取指向变量的值,当操作在左值时,就是将值设置给指向的变量。
使用指针修改值
package main
import "fmt"
func swap(a, b *int) {
*a, *b = *b, *a
}
func main(){
a, b := 1, 2
fmt.Println(a, b) // 1 2
swap(&a, &b)
fmt.Println(a, b) // 2 1
}
创建指针的另一种方法 — new()函数
Go语言还提供了另外一种方法来创建指针变量,方法如下:
str := new(string)
*str = "PHP is the best language in the world!"
fmt.Println(*str) // PHP is the best language in the world!
类型别名与类型定义
类型别名
类型别名规定:TypeAlias 只是 Type 的别名,本质上 TypeAlias 与 Type 是同一个类型,就像一个孩子小时候有小名、乳名,上学后用学名,英语老师又会给他起英文名,但这些名字都指的是他本人。
语法:type TypeAlias = Type
package main
import "fmt"
type IntAlias = int
func main() {
var a, b IntAlias = 3, 4
c := a + b
fmt.Printf("c has the value: %d", c) // 输出:c has the value: 7
}
类型定义type NewType Type
package main
import "fmt"
//类型定义
type NewInt int
//类型别名
type AliasInt = int
func main() {
var a NewInt
var b AliasInt
fmt.Printf("type ocf a:%T\n", a) //type of a:main.NewInt
fmt.Printf("type of b:%T\n", b) //type of b:int
}
// 区别:结果显示a的类型是main.NewInt,表示main包下定义的NewInt类型。b的类型是int。AliasInt类型只会在代码中存在,编译完成时并不会有AliasInt类型。