这篇文章的目标是做到足够的详细和深入,如有不合理的地方,望批评指正!!!
目录
Go 语言中的关键字
25个保留字:(代码编写过程中理解记忆)
36个预定义标识符:(认真理解一遍即可)
Go 语言中的数据结构
基本数据结构(变量未赋初值时默认类型零值)
基本数据结构的使用(几种变量声明的区别)
Go 语言中的运算符
Go 语言中变量的命名
Go 语言是如何定义函数的?
Go 语言实现数据类型转换
一个 Go 程序的基本结构
Go 程序启动时代码奔跑的顺序
包(package)的概念 - 模块、层次划分的另一种方式
可见性规则 - 我的东西给不给你用我说了算
注释 - 快速定位代码块
Go 语言基础知识拓展
fmt包中几种输出函数的比较
格式化说明符
知识小卡片
Go 代码中的标识符(变量名、指针、数组名...)与 C 家族中的其它语言相同是区分大小写的。有效的标识符必须以字符(或 _)开头,然后紧跟着 0 个或多个字符或 Unicode 数字,如:X56、group1、_x23、i、өԑ12。其中首字母大写的标识符可以被其他文件引用(public),首字母小写的标识符不能被其他文件引用(private)。
(按程序中可能出现的顺序排列)
package:定义包名,每一个 .go 文件一定属于某个包
import:包引用名词,用于引用其他包的内容
const:定义常量,const pi = 3.1415926
var:定义变量, var i int(默认零值) 也可赋初值 var i int = 5
map:一种映射结构 (key, value)
interface:接口结构
type:类型定义时使用
struct:结构体名词
func:定义函数
defer:推迟语句到函数返回时才执行
return:函数返回语句
if:判断语句
else:if 的备选项
goto:跳转语句,后接 label 名字
for:for循环
range:遍历迭代器时使用
switch:一种多路结构
continue:跳过当前for循环,开始下一次for循环
select:多路选其一
case:备选条件,一条case执行默认不执行下一条。
break:跳出循环,也可以跳出Labe(跳出多重循环)。
default:switch、select结构选不中时执行
go:定义协程用于并发
chan:通道
fallthrough:switch的case语句中使用,继续执行下个case
append:数组扩充函数
cap:计算容量函数
close:关闭读写连接函数
copy:拷贝函数
len:长度统计函数
make:给引用类型分配内存函数
new:给实类型分配内存函数
print:打印函数
println:打印函数(换行结尾)
panic:引出一个错误,终止程序
recover:恢复panic的函数
bool:布尔类型
byte:字节类型
complex:复数类型
complex64:64位复数类型
complex128:128位复数类型
uint:无符号整数类型
uint8:8位无符号整数类型
uint16:16位无符号整数类型
uint32:32位无符号整数类型
uint64:64位无符号整数类型
float32:32位浮点数类型
float64:64位浮点数类型
int:整数类型
int8:8位整数类型
int16:16位整数类型
int32:32位整数类型
int64:64位整数类型
string:字符串类型
nil:指针类型的零值
false:bool型变量的零值
true:bool型变量的非零值
itoa:一个自增变量
real:复数的实数部分
imag:
uintptr:
基本类型,如:int(0)、float(0.0)、bool(false)、string("");
结构类型(nil),如:struct、array、slice、map、channel;
只描述类型行为的(nil),如:interface。
type dog struct {
name string
age int
}
int: var i int; var i int = 5; i := int(5)
float32: var i float32; var i float = 5.0; i := float32(5.0)
bool: var i bool; var i bool = false; i := false
string: var i string; var i string = "jfajdk"; i := "string"
struct: var i dog; var i = dog{"xiao", 5}; i := dog{name:"xxx"}; i := dog{}; i := new(dog)
array: var arr [5]int; var arr = [5]int{1, 2}; arr := [5]int{1, 2, 3, 4};
slice: i := []int{}; i := array[0:4]; i := make([]int, 5, 10)
map: i := map[string]string{"name":"xiao"}; i := make(map[string]string, 10)
channel: var ch chan int (ch = make(chan int); ch := make(chan int, 5)
interface: type inf interface{}
关于 var := make() 和 new() 的区别:点击查看
运算符( 优先级:上高下低 )
1、 ^ !
( ^ 作为一元运算符表示按位取反 作为二元运算符表示异或,!为取反,用于 bool 型变量)
2、 * / % << >> & &^
( * 乘法,/ 除法(整形为整除,浮点型为除法),% 取余, << 数值二进制左移, >> 数值二进制右移, & 按位与, &^ 位操作 若运算符右边与左边不同保留左边位的值 若相同该位清零 )
3、 == != < <= >= >
( == 等于, != 不等于, < 小于, <= 小于等于, >= 大于等于, > 大于 )
4、 <-
( <- 用于 chan (通道) 输入到通道(chan<-para)或者从通道输出(para<-chan) )
5、 &&
( && and操作符 )
6、 ||
( || or操作符 )
&& 和 || 具有快捷性,左边决定结果后,右边不执行(技巧:计算过程复杂的表达式放在右边)。
官方推荐 驼峰命名法,即组成变量名的各单词首字母大写(如:WorkEnvConfig)。
func functionname(param type, param type) type {}
func functionname(param type, param type) (var type, var type) {}
官方推荐后面这种函数定义,前者是为了兼容程序员的编程习惯。
类型 B 的值 = 类型 B (类型 A 的值)
a := 5
b = float32(a)
package main // 包名
import ( // 引用外部包
"fmt"
)
const c = "C"
var v int = 5
type T struct{}
func init() { // 初始化函数,在程序执行前进行环配置等
}
func main() { // main函数,一个程序只能有一个
var a int
Func1()
// ...
fmt.Println(a)
}
func (t T) Method1() { // 与对象方法不同的结构体方法
//...
}
func Func1() { // 定义函数 Func1
//...
}
按顺序导入所有被 main 包引用的其它包,然后在每个包中执行如下流程:
如果该包又导入了其它的包,则从第一步开始递归执行,但是每个包只会被导入一次。
然后以相反的顺序在每个包中初始化常量和变量,如果该包含有 init 函数的话,则调用该函数。
在完成这一切之后,main 包也执行同样的过程,最后调用 main 函数开始执行程序。
这里的 init 函数( func init(){} )是 Go 语言特有的函数,它在包初始化后自动进行(main 函数执行之前),不是人为调用的,一般用来配置程序执行的环境。
更加详细的图解说明:点击查看
包是结构化代码的一种方式:每个程序都由包的概念组成,可以使用自身的包或者从其它包中导入(import)内容。你必须在源文件非注释的第一行指明这个文件属于哪个包(如 package fmt)。package main 表示一个可独立执行的程序,每个 Go 应用程序都包含一个名为 main 的包,只能有一个 main() 函数。注意:包名应全部用小写字母。(可能的bug:同属于 main 包不同源文件的函数不能被 main() 函数调用,其他的包却可以)
大写字母开头的标识符可以被外部包的代码所使用
小写字母开头的标识符在包内部是可见的,对外部包是不可见的
引用外部包的变量需要先 import “pkgname”然后使用 pkgname.var 表示
单行用双斜杠进行注释 // 此处为行注释
多行用 /* 此处可写多行注释 */ 进行块注释
Print: 输出到控制台(每一个操作数都按 %v 格式化)
Println: 输出到控制台并换行(每一个操作数都按 %v 格式化)
Printf : 只可以打印出格式化的字符串 fmt.Printf("%d",para),也可以直接输出字符串类型的变量
Sprintf:格式化并返回一个字符串没有输出。s := fmt.Sprintf("a %s", "string")
Fprintf:来格式化并输出到 io.Writers 而不是 os.Stdout。fmt.Fprintf(os.Stderr, “an %s\n”, “error”)
(fmt.Printf("%d", para)中的格式化说明)
%v 按变量本身类型输出(复数,切片要用到)万能的
%+v 实例的完整信息,添加字段名(如:结构体的域名)
%#v 实例的完整信息,添加字段名和变量的数据类型
对于整数类型:
%b 输出数值的二进制表示
%d 输出数值的十进制表示
%3d 输出定长的整数(若定义的长度不够,相当于%d)
%o 输出数值的八进制表示
%x 输出数值的十六进制表示(10-15: a - z )
%X 输出数值的十六进制表示(10-15: A - Z )
%c 输出数值对应Unicode码表示的字符
%e 输出科学计数表示 e
%E 输出科学计数表示 E
%n.me 输出宽度为 n 精确到小数点后 m 位的科学计数(舍去部分四舍五入)
%f 输出浮点数数值(精确到小数点后6位)
%n.mf 输出宽度为 n 精确到小数点后 m 位的浮点数数值(舍去部分四舍五入)
%g 根据情况选择 %e 或 %f 以产生更紧凑的(无末尾的0)输出
%G 根据情况选择 %E 或 %f 以产生更紧凑的(无末尾的0)输出
%n.mg 输出宽度为 n 数值位为 m 位的数值(舍去部分四舍五入)
%p 输出指针的值(指针指向变量的物理地址)
%s 输出字符串
%t 输出布尔型( true 或 false )
%T 变量的类型(现在编译器写代码,几乎用不到了)
更加详细的格式化说明符解释:点击这里
int 型是计算最快的一种类型
float32 精确到小数点后7位
float64 精确到小数点后15位
math 包中所有的数学运算函数都要求用 float64 类型
前缀 0 表示八进制数
前缀 0x 表示十六进制数
e 表示 10 的练成 (如:1e3=1000)
本文旨在提供一站式教程,欢迎阅读者提出宝贵的建议。