Goland 基础语法
1. 命名规则
-
go 语言中的函数名、变量名、常量名、类型名、语句标号和包名等所有的命名,都遵循一个简单的命名规则
-
必须以一个字母或下划线_开头,后面可以跟任意数量的字母、数字或下划线
-
go 语言中大小写字母认为是不同的
-
go 语言中有 25 个关键字,不能用于自定义名字
break | default | func | interface | select |
---|---|---|---|---|
case | defter | go | map | struct |
chan | else | goto | package | switch |
const | fallthrough | if | range | type |
continue | for | import | retrun | var |
还有 30 多个预定义的名字,用于内建的常量、类型和函数
内建常量
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
2. 变量
声明变量
语法格式: var 变量名 变量类型
package main
import "fmt"
func main() {
/*
变量不引用会报错
*/
// 1. 直接声明
var v1 int
var v2 int
// 2. 一次声明多个变量
var v3, v4 int
var (
v5 int
v6 int
)
fmt.Println(v1, v2, v3, v4, v5, v6)
}
变量初始化
package main
import "fmt"
func main() {
// 1. 直接初始化
var v1 int = 1
// 2. 自动推导初始化
var v2 = 2
// 3. 声明并初始化
v3 := 3
fmt.Println(v1, v2, v3)
}
变量赋值
package main
import "fmt"
func main() {
// 1. 直接赋值
var v1 int
v1 = 1
// 2. :=
v2 := 2
// 3. 多重赋值
var v3, v4 int
fmt.Println(v1, v2, v3, v4)
}
匿名变量
_
单下滑线表示匿名变量,为了防止变量为被引用报错
package main
import "fmt"
func test() (int, int) {
return 1,2
}
func main() {
// _单下滑线表示匿名变量,了不报错
v1, _ := test()
fmt.Println(v1)
}
3. 常量与枚举
const
关键字 定义常量
package main
import "fmt"
// 声明在函数外部
const filename = "123.txt"
const (
username = "admin"
password = "admin"
)
func main() {
// 声明在函数的内部
const filename = "456.txt"
fmt.Println(filename)
}
iota
常量生成器和枚举类型
package main
import "fmt"
// 枚举
func enums001() {
const (
v1 = 0
v2 = 1
v3 = 2
)
fmt.Println(v1, v2, v3)
// 输出结果 0 1 2
}
// 可省略的枚举
func enums002() {
const (
v1 = 0
v2
v3 = 1
v4
)
fmt.Println(v1, v2, v3, v4)
// 输出结果 0 0 1 1
}
// 定义自增的枚举类型
// iota默认值为0
// 往下依次自增
func enums003() {
const (
v1 = iota
v2
v3
v4
)
fmt.Println(v1, v2, v3, v4)
// 输出结果 0 1 2 3
}
// 计算枚举
func enums004() {
// b等于1左移
// 1<<(10 * 0) 1 << 0 相当于 1*2^0
const (
b = 1 << (10*iota)
kb
mb
gb
tb
pb
)
fmt.Println(b, kb, mb, gb, tb, pb)
// 输出结果
}
func main() {
//enums001()
//enums002()
//enums003()
enums004()
}
常见面试题
package main
import "fmt"
func main() {
// iota会接着走不会重新来
const (
a = iota
b
c
d = 9
e = 8
f = iota
g
)
fmt.Println(a,b,c,d,e,g,f)
// iota不在同一个const里,不是同一个
const (
x = iota
y
)
fmt.Println(x,y)
}
// 输出结果
// 0 1 2 9 8 5 6
4. 基本数据类型
int8 是有符号类型,uint8 是无符号类型
go 语言中不同类型的数据不能相加,会编译错误
类型 | 名称 | 长度 | 零值 | 说明 |
---|---|---|---|---|
bool | 布尔类型 | 1 | false | 值为 true 或 false, 不可以用数字代表 |
byte | 字节型 | 1 | 0 | uint8 |
rune | 字符类型 | 4 | 0 | 专用于存储 unicode 编码,等价于 uint32 |
int, uint | 整型 | 4 或 8 | 0 | 32 位或 64 位 |
int8, uint8 | 整型 | 1 | 0 | -128~127, 0~255 |
int16, uint16 | 整型 | 2 | 0 | -32768~32767, 0~65535 |
int32, uint32 | 整型 | 4 | 0 | -21 亿~21 亿, 0~42 亿 |
int64, uint64 | 整型 | 8 | 0 | |
float32 | 浮点型 | 4 | 0.0 | 小数位精确到 7 位 |
float64 | 浮点数 | 8 | 0.0 | 小数位精确到 15 位 |
complex64 | 复数类型 | 8 | ||
complex128 | 复数类型 | 16 | ||
uintptr | 整型 | 4 或 8 | 足以存储指针的 uint32 或 uint64 整数 | |
string | 字符串 | "" | utf-8 字符串 |
整型
package main
import (
"fmt"
"reflect"
)
func main() {
var v1 int
v1 = 123
v2 := 42
fmt.Println(reflect.TypeOf(v1))
fmt.Println(reflect.TypeOf(v2))
}
浮点型
package main
import (
"fmt"
"reflect"
)
func main() {
var f1 float32
f1 = 12.5
f2 := 13.66
fmt.Println(reflect.TypeOf(f1))
fmt.Println(reflect.TypeOf(f2))
}
布尔型
package main
import (
"fmt"
"reflect"
)
func main() {
// 只有true和false两个值
var b1 bool
b1 = false
fmt.Println(b1)
// 可以使用 == 或 != 得到布尔值
b2 := (1!=2)
fmt.Println(reflect.TypeOf(b2))
// 使用 ! 对布尔类型进行取反
b3 := !b2
fmt.Println(b3)
}
byte 字符型
package main
import (
"fmt"
"reflect"
)
func main() {
// 单引号赋值byte
var ch byte
ch = 'a'
fmt.Println(ch)
// 格式化输出
fmt.Printf("ch = %c\n", ch)
// uint8
fmt.Println(reflect.TypeOf(ch))
}
字符串
package main
import "fmt"
func main() {
// 字符串使用双引号赋值
var s1 string
s1 = "abc"
fmt.Println(s1)
// 取字符串中第一个字符
ch := s1[0]
fmt.Println(ch)
// 反引号用来创建原生的字符串字面量(原格式输出)
s2 := `hello
xxxxx
world
`
fmt.Println(s2)
}
5.fmt 包的使用
格式化参数列表
格式 | 含义 |
---|---|
%% | 一个%字面量 |
%b | 一个二进制整数值(基数为 2),或者是一个(高级的)用科学计数法表示的指数为 2 的浮点数 |
%c | 字符型。可以把输入的数字按照 ASCII 码相应转换为对应的字符 |
%d | 一个十进制数值(基数为 10) |
%e | 以科学记数法 e 表示的浮点数或者复数值 |
%E | 以科学记数法 E 表示的浮点数或者复数值 |
%f | 以标准记数法表示的浮点数或者复数值 |
%g | 以%e 或者%f 表示的浮点数或者复数,任何一个都以最为紧凑的方式输出 |
%G | 以%E 或者%f 表示的浮点数或者复数,任何一个都以最为紧凑的方式输出 |
%o | 一个以八进制表示的数字(基数为 8) |
%p | 以十六进制(基数为 16)表示的一个值的地址,前缀为 0x, 字母使用小写的 a-f 表示 |
%q | 使用 Go 语法以及必须时使用转义,以双引号括起来的字符串或者字节切片[]byte,或者是以单引号括起来的数字 |
%s | 字符串。输出字符串中的字符直至字符串中的空字符(字符串以'\0'结尾,这个'\0'即空字符) |
%t | 以 true 或者 false 输出的布尔值 |
%T | 使用 Go 语法输出的值的类型 |
%U | 一个用 Unicode 表示法表示的整型码点,默认值为 4 个数字字符 |
%v | 使用默认格式输出的内置或者自定义类型的值,或者是使用其类型的 String()方式输出的自定义值,如果该方法存在的话 |
%x | 以十六进制表示的整型值(基数为十六),数字 a-f 使用小写表示 |
%X | 以十六进制表示的整型值(基数为十六),数字 A-F 使用小写表示 |
输出
package main
import "fmt"
func main() {
// 整型
a := 16
// %b 二进制输出
fmt.Printf("%b\n", a)
fmt.Printf("%%\n", a)
}
输入
package main
import "fmt"
func main() {
// 定义接收输入内容的变量
var age int
fmt.Printf("请输入你的年龄: ")
// 接收输入
fmt.Scan(&age)
fmt.Printf("输入的年龄为: %d", age)
}
6. 类型别名
使用 type
关键字自定义类型
package main
import (
"fmt"
"reflect"
)
// type 自定义类型名 原类型
type myint int
func main() {
var v1 myint
v1 = 10
fmt.Println(reflect.TypeOf(v1))
}
// 输出结果: main.myint
7. 类型转换
go 语言不允许隐式转换
package main
import (
"fmt"
"reflect"
)
func main() {
var a byte
a = 97
var b int
b = int(a)
// 输出变量类型
fmt.Println(reflect.TypeOf(b))
}
8. 运算符
算数运算符
符号 | 说明 |
---|---|
+ | 相加 |
- | 相减 |
* | 相乘 |
/ | 相除 |
% | 求余 |
++ | 自增 |
-- | 自减 |
package main
import "fmt"
func main() {
a := 10
b := 6
// +
fmt.Println(a+b)
// -
fmt.Println(a-b)
// *
fmt.Println(a*b)
// /
fmt.Println(a/b)
// %
fmt.Println(a%b)
// ++
fmt.Println(a)
a++
fmt.Println(a)
// -
fmt.Println(b)
b--
fmt.Println(b)
}
关系运算符
符号 | 说明 |
---|---|
== | 等于 |
!= | 不等于 |
> | 大于 |
< | 小于 |
>= | 大于等于 |
<= | 小于等于 |
package main
import "fmt"
func main() {
a := 10
b := 6
// ==
fmt.Println(a==b)
// !=
fmt.Println(a!=b)
// >
fmt.Println(a>b)
// <
fmt.Println(a<b)
// >=
fmt.Println(a>=b)
// <=
fmt.Println(a<=b)
// ==
fmt.Println(a==b)
}
逻辑运算符
符号 | 说明 |
---|---|
&& | 与 |
|| | 或 |
! | 非 |
package main
import "fmt"
func main() {
a := 10
b := 6
c := 6
// &&
fmt.Println(a > b && b >= c)
// ||
fmt.Println(a > b || b > c)
// !
var d bool
fmt.Println(!d)
}
赋值运算符
运算符 | 描述 | 实例 |
---|---|---|
= | 简单的赋值运算符,将一个表达式的值赋给一个左值 | 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 |
<<= | 左移后赋值 | C <<= 2 等于 C = C << 2 |
>>= | 右移后赋值 | C >>= 2 等于 C = C >> 2 |
&= | 按位与后赋值 | C &= 2 等于 C = C & 2 |
^= | 按位异或后赋值 | C ^= 2 等于 C = C ^ 2 |
|= | 按位或后赋值 | C |= 2 等于 C = C | 2 |
位运算
运算符 | 描述 | 实例 |
---|---|---|
& | 按位与运算符"&"是双目运算符。 其功能是参与运算的两数各对应的二进位相与。 | (A & B) 结果为 12, 二进制为 0000 1100 |
| | 按位或运算符"|"是双目运算符。 其功能是参与运算的两数各对应的二进位相或 | (A | B) 结果为 61, 二进制为 0011 1101 |
^ | 按位异或运算符"^"是双目运算符。 其功能是参与运算的两数各对应的二进位相异或,当两对应的二进位相异时,结果为 1。 | (A ^ B) 结果为 49, 二进制为 0011 0001 |
<< | 左移运算符"<<"是双目运算符。左移 n 位就是乘以 2 的 n 次方。 其功能把"<<"左边的运算数的各二进位全部左移若干位,由"<<"右边的数指定移动的位数,高位丢弃,低位补 0。 | A << 2 结果为 240 ,二进制为 1111 0000 |
>> | 右移运算符">>"是双目运算符。右移 n 位就是除以 2 的 n 次方。 其功能是把">>"左边的运算数的各二进位全部右移若干位,">>"右边的数指定移动的位数。 | A >> 2 结果为 1 |
package main
import "fmt"
func main() {
var a uint = 60 /* 60 = 0011 1100 */
var b uint = 13 /* 13 = 0000 1101 */
var c uint = 0
c = a & b /* 12 = 0000 1100 */
fmt.Println(c)
c = a | b /* 61 = 0011 1101 */
fmt.Println(c)
c = a ^ b /* 49 = 0011 0001 */
fmt.Println(c)
c = a << 2 /* 240 = 1111 0000 a*(2**2) */
fmt.Println(c)
c = a >> 2 /* 15 = 0000 1111 a/(2*2) */
fmt.Println(c)
}
其他运算符
运算符 | 描述 | 实例 |
---|---|---|
& | 返回变量存储地址 | &a; 将给出变量的实际地址。 |
* | 指针变量。 | *a; 是一个指针变量 |
package main
import "fmt"
func main() {
var a int = 4
var b int32
var c float32
var ptr *int
/* 运算实例 */
fmt.Printf("a 变量类型为 = %T\n", a );
fmt.Printf("b 变量类型为 = %T\n", b );
fmt.Printf("c 变量类型为 = %T\n", c );
/* & 和 * 运算符实例 */
ptr = &a /* 'ptr' 包含了 'a' 变量的地址 */
fmt.Printf("a 的值为 %d\n", a);
fmt.Printf("*ptr 为 %d\n", *ptr);
}
运算符优先级
有些运算符拥有较高的优先级,二元运算符的运算方向均是从左至右。下表列出了所有运算符以及它们的优先级,由上至下代表优先级由高到低:
优先级 | 运算符 |
---|---|
5 | * / % << >> & &^ |
4 | + - \ ^ |
3 | == != < <= > >= |
2 | && |
1 | || |
当然,我们可以通过使用括号来临时提升某个表达式的整体运算优先级。