Go语言中为了防止格式化问题引发争论,制作了一个格式化工具gofmt
,在写完代码之后只需要gofmt -w *.go
就可以用统一的格式(比如对齐,缩进)来重写你的代码,-w
参数是重写你的文件,不加的话只会打印你的文件内容
RPC
调用的结构体里的参数也都需要首字母大写Go语言中语句也是由分号来结尾的,只是这些语句不显式的出现在源代码中,词法分析器会在编译过程中为每句语句的结尾添加上分号。
由于分号添加的规则,所以条件控制,循环,函数等语句的左大括号必须不能另起一行,否则会因为添加分号导致错误。
循环只有for
// 如同 C 的 for 循环
for init; condition; post { }
// 如同 C 的 while 循环
for condition { }
// 如同 C 的 for(;;) 循环
for { }
若你想遍历数组、切片、字符串或者映射,或从信道中读取消息, range 子句能够帮你轻松实现循环。
for key, value := range oldMap {
newMap[key] = value
}
可以省略第二个键,但是要省略第一个键必须用_
switch
语法除了正常的判断值,还能判断变量类型:
var t interface{}
t = functionOfSomeType()
switch t := t.(type) {
default:
fmt.Printf("unexpected type %T", t) // %T prints whatever type t has
case bool:
fmt.Printf("boolean %t\n", t) // t has type bool
case int:
fmt.Printf("integer %d\n", t) // t has type int
case *bool:
fmt.Printf("pointer to boolean %t\n", *t) // t has type *bool
case *int:
fmt.Printf("pointer to integer %d\n", *t) // t has type *int
}
switch
语法中的case
语句自带break
,所以不需要显式的写break
break
也可以显式的指定跳转到的标签位置,比如:
Loop:
for n := 0; n < len(src); n += size {
switch {
case src[n] < sizeOne:
if validateOnly {
break
}
size = 1
update(src[n])
case src[n] < sizeTwo:
if n+1 >= len(src) {
err = errShortInput
break Loop
}
return
的时候不需要指定return
的变量即可func ReadFull(r Reader, buf []byte) (n int, err error) {
for len(buf) > 0 && err == nil {
var nr int
nr, err = r.Read(buf)
n += nr
buf = buf[nr:]
}
return
}
defer
只能延迟函数,并且函数调用的实参会在遇到defer
语句的时候就被执行,同时多个defer
是类似栈式执行的,后来的先执行数据有两种分配方式new
和make
new
是用来分配内存的内建函数,但它不会初始化内存,只会将内存置零。new(T)
返回一个指针, 该指针指向新分配的,类型为T
的零值。make(T, args)
的目的不同于new(T)
。它只用于创建切片、映射和信道,并返回类型为T
(而非*T
)的一个已初始化 (而非置零)的值map
映射与切片一样也是引用类型,将映射传入函数中,并更改了该映射的内容,则此修改对调用者同样可见true
,不存在时返回false
,seconds, ok := timeZone[tz]
delete(timeZone, "PDT")
,要删除映射中的某项,可使用内建函数 delete,它以映射及要被删除的键为实参。 即便对应的键不在该映射中,此操作也是安全的。fmt.Println
可以直接使用变量当参数,打印变量的值fmt.Printf
类似C
语言的打印方式append
函数的定义如这样func append(slice []T, elements ...T) []T
append
会在切片末尾追加元素并返回结果 x := []int{1,2,3}
x = append(x, 4, 5, 6)
x := []int{1,2,3}
y := []int{4,5,6}
x = append(x, y...)
const (
// 通过赋予空白标识符来忽略第一个值
_ = iota // ignore first value by assigning to blank identifier
KB ByteSize = 1 << (10 * iota)
MB
GB
TB
PB
EB
ZB
YB
)
func (p *ByteSlice) Write(data []byte) (n int, err error) {
slice := *p
*p = slice
return len(data), nil
}
type Abser interface {
Abs() float64
}
func main() {
var a Abser
f := MyFloat(-math.Sqrt2)
a = f // a MyFloat implements Abser
fmt.Println(a.Abs())
}
type MyFloat float64
func (f MyFloat) Abs() float64 {
if f < 0 {
return float64(-f)
}
return float64(f)
}
str, ok := value.(string)
import (
"fmt"
"io"
"log"
"os"
)
var _ = fmt.Printf // For debugging; delete when done. // 用于调试,结束时删除。
var _ io.Reader // For debugging; delete when done. // 用于调试,结束时删除。
func main() {
fd, err := os.Open("test.go")
if err != nil {
log.Fatal(err)
}
// TODO: use fd.
_ = fd
}