// 单行注释
/* xxxx */ 编译器忽略该区间,其间都被认为是注释内容。虽然Go支持,但很少使用,一般都用多行//
//包注释
package main
import "fmt"
/*
x int
y int
*/
// x int
// y int 多行注释
func main() {
fmt.Println("zzzz") //打印
//TODO: 将来完成,一把是这个任务没写完,加入这个注释,方便下次继续完成这个任务
}
// TODO: 将来完成,推荐
// NOTE: 请注意
// Deprecated: 告知已经过期,建议不要使用。未来某个版本可能移除
标识符采用CamelCase驼峰命名法
如果只在包内可用,就采用小驼峰命名
如果要在包外可见,就采用大驼峰命名
userName 小驼峰命名 首字母小写中间大写
UserName 大驼峰 首字母大写 中间大写 区别在与包外可见
user_name snake 蛇形命名
简单循环变量可以使用i、j、k、v等
一般用简单的英文单词
条件变量、循环变量可以是单个字母或单个单词,Go倾向于使用单个字母。Go建议使用更短小
常量驼峰命名即可
在其他语言中,常量多使用全大写加下划线的命名方式,Go语言没有这个要求
对约定俗成的全大写,例如PI
函数/方法的参数、返回值应是单个单词或单个字母
函数可以是多个单词命名
类型可以是多个单词命名
方法由于调用时会绑定类型,所以可以考虑使用单个单词
包以小写单个单词命名,包名应该和导入路径的最后一段路径保持一致
接口优先采用单个单词命名,一般加er后缀。Go语言推荐尽量定义小接口,接口也可以组合
25个关键字
break default func interface select
case defer go map struct
chan else goto package switch
const fallthrough if range type
continue for import return var
一个名字,本质上是个字符串,用来指代一个值
只能是大小写字母、数字、下划线,也可以是Unicode字符
Unicode字符也可以是中文 但是不推荐标识符采用中文的字符
不能以数字开头
不能是Go语言的关键字
不能和关键字冲突
尽量不要使用“预定义标识符”,否则后果难料
大小写敏感
它是值,不是标识符,但本身就是常量,不能被修改。
Go语言中,boolean、rune、integer、float、complex、string都是字面常量。其中,rune、
integer、float、complex常量被称为数值常量。
100
0x6162 0x61_62_63
3.14
3.14e2
3.14E-2
'测' //字符 ''单引号中 有且仅有一个
'\u6d4b'
'\x31'
'1'
'\n'
"abc" "\x61b\x63" // 字符串 ""双引号中,可以有一个也可以多个
"测试" "\u6d4b试"
"\n"
true
false
iot
‘1’ "1"的区别
‘1’ 这个代表有且只有一个数字就是1 代表的是字符
“1” 这个代表和这个字符串里有1 代表的是字符串
常量:使用const定义一个标识符,它所对应的值,不允许被修改。
对常量并不要求全大写加下划线的命名规则。
常量必须在定义是赋值,并且后面不能再变化
数组不能赋值给常量
const 常量名 = 初值 常量必须在定义是直接赋初值
package main
import "fmt"
func main() {
const a int = 100 // 指定类型定义常量并赋值
const b = "abc" // 定义常量,等式左边未给出类型,将进行类型推导
const c = 12.3
const d = 'T'
fmt.Printf("%T\n", a)
fmt.Printf("%T\n", b)
fmt.Printf("%T\n", c)
fmt.Printf("%T\n", d)
}
int %T 输出值对应的类型
string
float64
int32
批量定义
const (
c = "abc" // 类型推导 String类型
d = 100 // 字面常量 无类型常量100 关联, 默认推导int类型
e uint8 = 100 // 无类型常量100 ,和左边有类型常量uint8类型 e
// int 8bits => 1bytes -128~127 0~255
f float32 = 1.5 //flost32类型
g = true //bool类型
)
package main
import "fmt"
func main() {
var a // 错误,无法推测类型
var b int // 正确,只声明,会自动赋为该类型的零值
var c, d int // 正确,声明连续的同类型变量,可以一并声明,会自动赋为该类型的零值
var b = 200 // 错误,b多次声明,第二行已经声明过
b = 200 //正确
var f, e int = 11, 22 // 正确
}
// 用var声明,立即赋值,或之后赋值
var b int // 正确,只声明,会自动赋为该类型的零值
b = 200
b = 300
b = "4" // 错误,类型错误
var a = 100 // 右边无类型常量,缺省类型是int,左边a没有指定类型,用到类型推导,所以a为int类型 var a int = 100
var a // 错误的,因为没有右边,go是强类型语言,此时不能利用右边来推导,左边又没有指定类型,所以错误
var a int // 正确,指定了类型,但是没有赋值。go中正确的原因是 零值可用。int的零值是0
var a int32 = 200 // 正确,指定了类型,也赋值。不会采用类型推导
// 批量赋值
var a int, b string // 错误,批量不能这么写
var ( // 正确
a int
b string
)
var ( // 错误,变量必须有类型,但没有给类型,也不能使用值来推导类型
a
b
)
var a int, b string = 111, "abc" // 错误,多种类型不能这么写,语法不对
var (
a int = 111
b string = "abc"
) // 正确,建议批量常量、变量都这么写
var (
a = 111
b = "abc"
) // 正确,类型推导
变量:标识符的指向的值建立后,可以改变
a := 100 // 赋值语句,短格式变量定义语句,定义变量。定义了变量标识符a,右边可以用来推导a的类型为int
相当于 var a = 100 同样的 没有定义类型 通过字面量来推导a的类型
不可以重复定义类型
var a int //零值0
a := 100 //错误的 因为前面已经定义类型了 短格式在定义类型是不允许的
有特例:
var a int
a,b := 123,"abcd" //竟然可以?在这里a不能重新定义为新类型,a被检测到了,go语言上只能迁就你了,但是要求a同类型,b是新定义的
短格式要求:
a, b := 123, "abcd"
a, b, c := 123, "abcd", 12.5 // 短格式批量同一行定义,因为短格式不能指定类型,所以采用类型推导,左右要求个数一致
短格式
使用 := 定义变量并立即初始化
只能用在函数中,不能用来定义全局变量
不能提供数据类型,由编译器来推断
go的数据交换是特殊的 具体的特殊就是在定义和赋值后,想相当于对变量名进行了快照的处理,在交换数据时,是直接调用快照前,变量指向的数值
package main
import "fmt"
func main() {
a := 100
b := 200
a, b = b, a //按照别的语言当a=b时,a=200了,后面的b=a肯定是调用的是a=200,但是go不是,go依旧调用的是前面a=100,相当于是快照了
fmt.Println(a, b)
}
[Running] go run "f:\goprpject\test2\m.go"
200 100
//一定是批量定义const这种,如果是单行 iota一直都是0
// iota 定义成批常量,iota从0,从成批的第一行
package main
import (
"fmt"
)
func main() {
const (
a = iota //第一行为0
b // 1
c // 2
)
fmt.Println(a, b, c)
}
0 1 2
package main
import (
"fmt"
)
func main() {
const (
a = iota + 1 // 1
b // 2 批量定义的时候,下面一行可以继承上面的表达式 b = iota +1
c // c = iota + 1 iota=2 c=3
_ // 空白标识符,黑洞 _=iota+1 iota =4
d
t = 100
_
_
e // ? e=100 //批量定义的时候,下面一行可以继承上面的表达式
)
fmt.Println(a, b, c, d, t, e)
}
1 2 3 5 100 100
const (
m = 100 // iota:0
n // n : 100, iota : 1
a = iota * 2 // 2 * 2
b = iota * 2 // 3 * 2
c
d
)
fmt.Println(a, b, c, d) // 4 6 8 10
总结:iota只能用于常量,是在成批定义和序列有关的常量定义,iota在成批定义中,可以认为是行索引,可以应用为日期和月份
索引和序号的区别:序号一般是从1开始的,行索引一般从0开始
变量已经被声明,但是未被显式初始化,这是变量将会被设置为零值。其它语言中,只声明未初始化的变量误用非常危险,但是,Go语言却坚持“零值可用”理念。在Go语言中合理利用零值确实带来不小的便利
*每一个标识符对应一个具有数据结构的值,但是这个值不方便直接访问,程序员就可以通过其对应的标识符来访问数据,标识符就是一个指代。一句话,标识符是给程序员编程使用的。*标识符就是给人来看的,经过机器编译后,就是以内存地址的形式存在。
标识符写源代码时候,用来指代某个值的。编译后还有变量、常量标识符吗? 没有了,因为数据在内存中,内存访问靠什么?地址,标识符编译后就没有了就换成了地址了。
源代码本质是文本文件
编译 ,源代码编程成二进制可执行文件。运行这个磁盘上的二进制可执行文件,运行在当前OS上,变成进程,变量、常量、值在这块内存中放着
在Go语言中,在.go文件中的顶层代码中,定义的标识符称为包级标识符。如果首字母大写,可在包外可见。如果首字母小写,则包内可见。
在a.go的文件中
package main
// 无类型常量定义
var a = 20 // int
var b = 3.14 // float64
在m.go的文件中
package main
import "fmt"
func main() {
fmt.Println(a, b)
}
使用建议
定义在函数中,包括main函数,这些标识符就是局部标识符。
使用建议
在函数中定义的标识符
const定义局部常量
var定义局部变量
可以指定类型,也可以使用无类型常量定义
延迟赋值必须指定类型,不然没法确定零值
有相关关系的,可以批量定义在一起
在函数内,直接赋值的变量多采用短格式定义
类型bool,定义了2个预定义常量,分别是true、false。
bool在go中不是int类型,也不是其他整数类型。在go中,bool就是布尔型,和整型没有关系,就是完全不同的类型。
长度不同:int8、int16(C语言short)、int32、int64(C语言long)
长度不同无符号:uint8、unit16、uint32、uint64
自动匹配平台:int、uint
以上类型均不相同,但是独立的类型
package main
import "fmt"
func main() {
var a = 20
b := 30
var c int = 40
fmt.Printf("%T, %T, %T, %d\n", a, b, c, a+b+c)
}
int, int, int, 90
看区别
package main
import "fmt"
func main() {
var a = 20
b := 30
var c int = 40
fmt.Printf("%T, %T, %T, %d\n", a, b, c, a+b+c)
var d int64 = 50
fmt.Printf("%T, %T\n", d, a+d) // a是int类型 d是int64 不是一个类型 必须同类型才能相加
}
package main
import "fmt"
func main() {
var a = 20
b := 30
var c int = 40
fmt.Printf("%T, %T, %T, %d\n", a, b, c, a+b+c)
var d int64 = 50
fmt.Printf("%T, %T\n", d, a+int(d))
}
int64, int //d是int64 将强制类型转换为int类型
%d 数值形式,往往用于整数
%T 表示type,取值的类型
把一个值从一个类型强制转换到另一种类型,有可能转换失败。
package main
import "fmt"
func main() {
var d int64 = 50
fmt.Printf("%T, %d\n", d, d)
fmt.Printf("%T, %s; %T, %d; %T, %f\n", string(d), string(d), rune(d),
rune(d), float32(d), float32(d))
}
输出如下
int64, 50
string, 2; int32, 50; float32, 50.000000
%T 表示type,取值的类型
%d digital 数值形式,往往用于整数
%s 用string类型的值
%q 带字符串类型引号的%s,quote引号
%c character,字符输出
%f float浮点数输出,默认精度为6
字符表达,必须使用单引号引住一个字符。
单引号留给了表示字符,字面量表达,本质上是int32(rune)或byte(uint8)
双引号和反引号用来表示字符串字面量。
type rune = int32 // rune是int32的别名,4个字节,可以是Unicode字符
type byte = uint8 // byte是uint8的别名,1个字节
package main
import "fmt"
func main() {
var c rune = '中' // 字符用单引号
fmt.Printf("%T, %[1]c, %[1]d\n", c) // int32, 中, 20013
}
[1] 代表的是指定后面的序号
c = 'a'
fmt.Printf("%T, %c, %d\n", c, c, c) // int32, a, 97
var d byte = '中' // 错误,超出byte范围 byte是1个字节 但是中是四个字节的 转换出来超出byte的范围
float32:最大范围约为3.4e38,通过math.MaxFloat32查看
float64:最大范围约为1.8e308,通过math.MaxFloat64查看
打印格式化符常用%f
// fmt的格式化,参考包帮助 https://pkg.go.dev/fmt
f := 12.15
fmt.Printf("%T, %f\n", f, f) // 默认精度6
fmt.Printf("%.3f\n", f) // 小数点后3位
fmt.Printf("[%3.2f]\n", f) // 宽度撑爆了,中括号加上没有特殊含义,只是为了看清楚占的
打印宽度
fmt.Printf("[%6.2f]\n", f) // 宽度为6,保留两位小数
fmt.Printf("[%-6.2f]\n", f) // 左对齐