Go:学习笔记兼吐槽(1)html
a. 通用:bash
参数 | 含义 |
---|---|
%v | 值的默认格式表示 |
%+v | 相似%v,但输出结构体时会添加字段名 |
%#v | 值的Go语法表示 |
%T | 值的类型的Go语法表示 |
%% | 百分号 |
b. 布尔值:app
参数 | 含义 |
---|---|
%t | 单词true或false |
c. 整数:函数
参数 | 含义 |
---|---|
%b | 表示为二进制 |
%c | 该值对应的unicode码值 |
%d | 表示为十进制 |
%o | 表示为八进制 |
%q | 该值对应的单引号括起来的go语法字符字面值,必要时会采用安全的转义表示 |
%x | 表示为十六进制,使用a-f |
%X | 表示为十六进制,使用A-F |
%U | 表示为Unicode格式:U+1234,等价于"U+%04X" |
d. 浮点数与复数的两个组分:post
参数 | 含义 |
---|---|
%b | 无小数部分、二进制指数的科学计数法,如-123456p-78 |
%e | 科学计数法,如 -1234.456e+78 |
%E | 科学计数法,如 -1234.456E+78 |
%f | 有小数部分但无指数部分,如123.456 |
%F | 等价于 %f |
%g | 根据实际状况采用 %e 或 %f 格式(以得到更简洁、准确的输出) |
%G | 根据实际状况采用 %E 或 %F 格式(以得到更简洁、准确的输出) |
e. 字符串和[]byte:学习
参数 | 含义 |
---|---|
%s | 直接输出字符串或者 []byte |
%q | 该值对应的双引号括起来的go语法字符串字面值,必要时会采用安全的转义表示 |
%x | 每一个字节用两字符十六进制数表示(使用a-f) |
%X | 每一个字节用两字符十六进制数表示(使用A-F) |
f. 指针:ui
参数 | 含义 |
---|---|
%p | 表示为十六进制,并加上前导的 0x |
狂吐槽,这种方式灵活多变,能够知足全部要求,但实际上大多数状况下,转 string 就是想看到一个值本来的样子,为何不能每种类型给个默认参数呢?若是有不一样需求再传参啊,就像 .net 里的 ToString() 方法。编码
func FormatBool(b bool) string
func FormatInt(i int64, base int) string
func FormatUint(i uint64, base int) string
func FormatFloat(f float64, fmt byte, prec, bitSize int) string
func Itoa(i int) string // Itoa是FormatInt(i, 10) 的简写
base:指定进制(2到36)
fmt:表示格式:'f'(-ddd.dddd)、'b'(-ddddp±ddd,指数为二进制)、'e'(-d.dddde±dd,十进制指数)、'E'(-d.ddddE±dd,十进制指数)、'g'(指数很大时用 'e' 格式,不然 'f' 格式)、'G'(指数很大时用 'E' 格式,不然 'f' 格式)。
prec:精度(排除指数部分):对 'f'、'e'、'E',它表示小数点后的数字个数;对 'g'、'G',它控制总的数字个数。若是 prec 为-1,则表明使用最少数量的、但又必需的数字来表示 f。
bitSize:表示 f 的来源类型(32:float3二、64:float64),会据此进行舍入。
继续狂吐槽,这种方式太二了,参数都是 64 位的,传个 int32 还不行,必须先强转成 int64,这不是浪费效率吗。并且每种参数类型都对应一个方法,方法名还不一样,由于,Golang 不支持方法重载。
func ParseInt(s string, base int, bitSize int) (i int64, err error)
func ParseUint(s string, base int, bitSize int) (n uint64, err error)
func ParseFloat(s string, bitSize int) (f float64, err error)
func FormatBool(b bool) string
func Atoi(s string) (i int, err error) // Atoi是ParseInt(s, 10, 0)的简写。
base:指定进制(2到36),若是base为0,则会从字符串前置判断,"0x"是16进制,"0"是8进制,不然是10进制。
bitSize:指定结果必须能无溢出赋值的整数类型,0、八、1六、3二、64 分别表明 int、int八、int1六、int3二、int64;简单的说,若是这个 string 所表示的真实值超出了 baseSize 所指定的类型的范围,那么就会发生溢出,虽然这个返回值是 64 位的,然并卵,看下面的例子就明白了。
var str string = "999"
var num int64
num, _ = strconv.ParseInt(str, 10, 8)
fmt.Println(num) // 结果是 127
都无力吐槽了。
首先这些方法返回两个值(Golang 容许函数有多个返回值),第一个是转换结果,64 位的,若是你须要的是一个 32 位的值,那么还须要强制转换。
第二个是错误信息,若是不想看错误信息,能够用 _ (详见空标识符)忽略。当发生错误时,返回的值是默认值 0。这就是说,你没办法 try catch 了。
值类型: int、float、string、bool、数组、结构体struct
引用类型:指针、切片slice、map、管道channel、interface
注意:数组也是值类型,跟其余语言不一样。
值类型一般在栈中分配,引用类型一般在堆中分配,当没有任何一个引用指向该引用类型的地址时,GC 将其回收。
这里说的是一般,而不是绝对,这是因为 Golang 中的逃逸机制致使的,这个逃逸机制之后再说。
_
是一个特殊的标识符,称为空标识符。它能够表明其余任何的标识符,可是它对应的值会被忽略,因此仅能做为占位符使用。
Golang 中没有 public、private 等访问修饰符,而是规定,常量名、变量名、函数名的首字母若是是大写的,则能够被其余包访问,若是是小写的,则其余包不能访问。
a % b
的运算规则是 a - a / b * b
Golang 中,只有 i++
,而没有 ++i
。
自增和自减只能当作一个独立的语句使用,j = i++
、if i++ > 0
等写法都是错的。
Golang 不支持三元运算符,请用 if else
。
这个我忍。
基本语法:
if 条件表达式 {
语句块
} else {
语句块
}
()
括起来,在通常状况下,加了 () 也不会报错,可是不建议这么作。若是条件表达式用有定义变量(见下文),那么加了 () 会报错。{}
中,即使该语句块中只包含一条语句。(自动加分号致使)else
必须写在 if
语句块的 }
后面,不能另起一行。(自动加分号致使)if age := 20; age > 18 {
fmt.Println("已成年")
} else {
fmt.Println("未成年")
}
我又要开始吐槽了,在条件表达式里声明一个变量,看起来不错。可是,这里的声明方式,只能用
:=
的方式,不能使用var
关键字来声明,这就意味着你不能显示给它指定类型,只能是推导出来的默认类型。而前面也已经说过了,Golang 没有隐式转换,不一样类型之间是没法比较的。
遇到这种状况,若是
n
的类型没法改变,仍是只能把age
定义在外面。
最要命的还不是这里,而是在 for 循环里,for 循环里是确定要定义一个循环变量的,不论是在里面仍是外面,而后这问题就少不了了。
基本语法
switch 表达式 {
case 表达式1:
语句块
case 表达式2, 表达式3,...:
语句块
default:
语句块
}
case
后面能够跟多个表达式,逗号隔开,只要其中一个匹配成功就可进入case
的语句块中不须要加 break
,默认状况下,语句块执行完成后就退出 switchswitch
后能够不带表达式,相似 if else
分支来使用var age int = 20
switch {
case age > 18:
fmt.Println("已成年")
default:
fmt.Println("未成年")
}
switch
后也能够直接声明一个变量,以分号结束,和 if
相似,但这种写法不推荐使用。switch age := 20; {
case age > 18:
fmt.Println("已成年")
default:
fmt.Println("未成年")
}
case
语句块后增长 fallthrough
,则会执行下一个 case
。只能穿透一层 case
。switch
语句还能够被用于 type-switch 来判断某个 interface
变量中实际指向的变量类型。基本语法:
for i := 1 ; i < 10; i++ {
语句块
}
也能够将循环变量定义或循环变量迭代写在其余地方,但分号不能省略,这点跟 .net 等语言是同样的。
i := 1
for ;i < 10; i++ {
语句块
}
第二种写法,for 后面能够仅有循环条件判断
i := 1
for i < 10 {
语句块
i++
}
第三种写法:
for {
语句块
}
这种写法等价于for ; ; {}
,是一个死循环,一般须要配合 break
使用。
Golang 中没有 while 和 do while,若是要实现相似的效果,就只能用这个方式。
for range
方式用于遍历容器类型,如字符串、数组、切片、映射。
var str string = "hello"
for index, value := range str {
fmt.Printf("%v %c\n", index, value)
}
for range
遍历字符串的时候是按字节的方式遍历的,看以下示例:
var str1 string = "hello 北京"
for index, value := range str1 {
fmt.Printf("%v %c\n", index, value)
}
//运行结果
0 h
1 e
2 l
3 l
4 o
5
6 北
9 京 //注意这里 index 从 6 直接跳到了 9,由于 UTF-8 编码一个汉字占 3 个字节
break
用于跳出循环,在 .net 等语言中,break
只能用于跳出当前循环,而在 Golang 中,能够经过标签指明要跳出哪一层的循环。有点相似 goto
了。
lable1:
for i := 0; i < 10; i++{
for j := 0; j < 10; j ++{
if j == 2{
break lable1
}
fmt.Println(j)
}
}
continue
和 break
同样,也能够经过标签指定要继续的是哪一层循环。