ps: 并不是一个小白入门,需要掌握
linux
,网络
,或者一门编程语言
Go语言的基础语法
📅 2024年4月26日
📦 使用版本为1.21.5
入门程序
⭐️和java
类似,也是有包的概念,它的程序入口也是main
函数,如果一个go程序有main
函数,那么它的包一定就是main
包
1️⃣ 在Go
中,加不加;
都可以
go
package main
import "fmt"
func main() {
fmt.Println("Hello World");
};
2️⃣ 在命令行中可以执行go run [go文件]
来直接运行,获取go build
3️⃣ 多个包可以合并导包
go
package main
//导入多个包
import (
"fmt"
"time"
)
func main() {
fmt.Println("Hello World")
time.Sleep(1)
}
4️⃣ 花括号必须和主体变量名在同一行(比较反人类的一点),这个是它的语法问题,强制代码风格
包
⭐️ go
的包和java
的差不多,在Go
语言中,一个包(package
)是由一组相关的源代码文件组成的,这些文件通常位于相同的目录下,共同服务于一个特定的目的。创建一个新的Go
文件(.go文件
)时,该文件即被视为该目录下现有包的一部分,或者如果该目录下还没有包,则创建了一个新的包
在Go中,程序是通过将包链接在一起来构建的,也可以理解为最基本的调用单位是包,而不是go文件。包其实就是一个文件夹,包内共享所有源文件的变量,常量,函数以及其他类型。包的命名风格建议都是小写字母,并且要尽量简短
go
packge main //表示这个函数属于main包
导入
⭐️ 导入其实也和Java/Python
差不多
go
import "fmt"
import e "fmt" //给包起别名
⭐️ 如果有多个包导入可以简写语法
go
import(
"fmt"
"match"
)
⭐️ 或者只导入不调用,可以使用_
来匿名调用
go
import(
"fmt"
_ "match" //下划线表示匿名调用
)
⭐️ 在Go中完全禁止循环导入,不管是直接的还是间接的。例如包A导入了包B,包B也导入了包A,这是直接循环导入,包A导入了包C,包C导入了包B,包B又导入了包A,这就是间接的循环导入,存在循环导入的话将会无法通过编译
init函数
⭐️ 在导包后,如果存在init
函数则对该函数进行定义,这是一个特殊的函数,每个含有该函数的包都会首先
执行这个函数
⭐️ 变量除了可以在全局声明中初始化,也可以在init
函数中初始化
go
package main
var a int
var c int
func init() {
a = 1
c = 2
}
func main() {
println(a)
println(c)
}
⭐️ 一个包中可以含有多个init
,但是一个源文件只能包含一个init
⭐️ 它主要定义可以在程序执行之前对程序进行检验和修复
导出
⭐️ 在Go
中的访问控制和java
不同,它是直接通过命名来实现,首字母大小为对外暴露,首字母小写表示只对内部开放
1️⃣ 在var
包下新建了一个Test
包(其实就是创建文件夹)
2️⃣ test.go
文件内容
java
package Test
func test() { //小写字母内部函数
println("hello world")
}
func Test() { //大写字母可以对外的函数
test()
}
3️⃣ 使用import
导入包后,调用
java
package main
import "var/Test"
func main() {
Test.Test()
Test.test() //报错
}
对外暴露的函数和变量可以被包外的调用者导入和访问,如果是不对外暴露的话,那么仅包内的调用者可以访问,外部将无法导入和访问,该规则适用于整个Go语言,例如后续会学到的结构体及其字段,方法,自定义类型,接口等等
私有
⭐️ go
中约定,一个包内名为internal
包为私有包,其它的包将无法访问私有包中的任何东西。下面看一个例子
1️⃣ interal.go
中文件如下
java
package Test_internal
func Internal() {
println("我是内部包中的Test_internal包中的函数")
}
2️⃣ 此时internal
包是Test
的内部包,Test2
将无法访问
3️⃣ var
包也不可以访问,对于var
包来说internal
包不是它的内部包
运算符
⭐️ 和平常语言的运算符差不多
Precedence Operator
5 * / % << >> & &^
4 + - | ^
3 == != < <= > >=
2 &&
1 ||
⭐️ 有一点需要稍微注意下,go语言中没有选择将~
作为取反运算符,而是复用了^
符号,当两个数字使用^
时,例如a^b
,它就是异或运算符,只对一个数字使用时,例如^a
,那么它就是取反运算符。go也支持增强赋值运算符,如下
go
a += 1
a /= 2
a &^= 2
⭐️ Go
没有虽然有自减运算符,但是它们被降级为statement
语句,而且运算符只能位于操作数的后面,且没有返回值!!!
在编程语言中,"statement"(语句)是一个基本的概念,它指的是完成一个具体任务或操作的最小单位代码。语句是构成程序的基本构建块,用于向计算机发出指令,告诉它执行什么样的操作。根据不同的编程语言,语句的形式和功能会有所不同,但它们通常包括赋值、条件判断、循环控制、函数调用、表达式计算等
go
package main
func main() {
var a = 10
a-- //减减后为 9
println(a)
println(a--) //错误没有,在go中自增自减都没有返回值
println(--a) //错误运算符要在操作数后
}
字面量
⭐️和java/python
的差不多,按照计算机科学的术语来讲是用于表达源代码中一个固定值的符号,也叫字面值,
顾名思义就是字面上的值
1️⃣整型字面量
为了便于阅读,允许使用下划线_
来进行数字划分,但是仅允许在前缀符号之后 和数字之间使用。
十进制:无前缀,如 24
二进制:前缀 0b 或 0B,如 0b00(表示十进制的0)
八进制:前缀
0o
或0O
,如0O24
(表示十进制的20)十六进制:前缀
0x
或 0X,如 0x00(表示十进制的0)
go
24 // 24
024 // 24
2_4 // 24
0_2_4 // 24
10_000 // 10k
100_000 // 100k
0O24 // 20
0b00 // 0
0x00 // 0
0x0_0 // 0
2️⃣ 浮点数字面量
通过不同的前缀可以表达不同进制的浮点数
go
0.
72.40
072.40 // == 72.40
2.71828
1.e+0
6.67428e-11
1E6
.25
.12345E+5
1_5. // == 15.0
0.15e+0_2 // == 15.0
0x1p-2 // == 0.25
0x2.p10 // == 2048.0
0x1.Fp+0 // == 1.9375
0X.8p-0 // == 0.5
0X_1FFFP-16 // == 0.1249847412109375
0x15e-2 // == 0x15e - 2 (integer subtraction)
3️⃣ 复数字面量
go
0i
0123i // == 123i
0o123i // == 0o123 * 1i == 83i
0xabci // == 0xabc * 1i == 2748i
0.i
2.71828i
1.e+0i
6.67428e-11i
1E6i
.25i
.12345E+5i
0x1p-2i // == 0x1p-2 * 1i == 0.25i
4️⃣ 字符字面量
字符字面量必须使用单引号括起来''
,Go中的字符完全兼容utf8
。
go
'a'
'ä'
'你'
'\t'
'\000'
'\007'
'\377'
'\x07'
'\xff'
'\u12e4'
'\U00101234'
5️⃣ 转义字符
Go中可用的转义字符
text
\a U+0007 响铃符号(建议调高音量)
\b U+0008 回退符号
\f U+000C 换页符号
\n U+000A 换行符号
\r U+000D 回车符号
\t U+0009 横向制表符号
\v U+000B 纵向制表符号
\\ U+005C 反斜杠转义
\' U+0027 单引号转义 (该转义仅在字符内有效)
\" U+0022 双引号转义 (该转义仅在字符串内有效)
6️⃣字符串字面量
字符串字面量必须使用双引号""
括起来或者反引号(反引号字符串不允许转义)
go
`abc` // "abc"
`\n
\n` // "\\n\n\\n"
"\n"
"\"" // `"`
"Hello, world!\n"
"今天天气不错"
"日本語"
"\u65e5本\U00008a9e"
"\xff\u00FF"
风格
⭐️ go
官方提供了一个gofmt
用来格式化go
代码
⭐️ 花括号必须和函数名要在同一行不能换行
⭐️ 花括号不能省略
⭐️ 运算符号的间隔:优先级高的运算符紧凑,低的则间隔明显