展开
type ByteSize float64
const (
_ = iota // iota 是枚举器(0 开始,每行+1),用 _ 忽略第一个值
KB ByteSize = 1 << (10 * iota)
MB
GB
)
x := 10
var (
home = os.Getenv("HOME")
user = os.Getenv("USER")
)
var err error.Error
res, err := get()
:=
。func init() {
这里执行的代码会在当前包被 import 时执行。
}
展开
展开
// 这样初始化拿到的是该类型的零值的指针,里面每个属性都是对应类型的零值
f := &File{} 或 f := new(File)
f.fd = fd
f.name = name
// 填写每个属性
f := &File{fd, name, nil, 0}
// 通过 label 可以只赋值部分属性
f := &File{fd: fd, name: name}
展开
a := [100]int{}
var b [10]int
c := [...]int{1, 2, 3}
s := make([]int, 100)
var nums []float
var s [][]byte
// 定义了一个 5 行 8 列的数组
picture := make([][]uint8, 5)
for i := range picture {
picture[i] = make([]uint8, 8)
}
type LinesOfText [][]byte
text := LinesOfText{
[]byte("good"),
[]byte("gophers"),
}
// 数组整体赋值是拷贝
a := [1]int{1}
b := a // 此时 a 和 b 不是同一个数组
b[0] = 2 // a = [1], b = [2]
// slice 的整体赋值是指向同一个底层数组
s := []int{1}
t := s
t[0] = 2 // s = [2], t = [2]
起点可以省略,不能像 python 一样用负数。切片底层指向同一块空间。
s := a[1:3]
prefix := str[:len(str)-10]
代表容量(cap)为 max-low,容量会影响 append 操作的具体实现。字符串不适用。
a[low : high : max]
展开
var timeZone = map[string]int{
"UTC": 0,
"CST": -6,
"PST": -8,
}
timeZone["MST"] // 0,不存在的 key,会得到 value 类型的零值。
t, ok := timeZone["MST"] // 会得到 0, false
if _, ok := timeZone["MST"]; ok { // 如果只是判断是否存在
delete(timeZone, "UTC") // 删除某个 key
&timeZone["UTC"] // 是错误的, cannot take address of timeZone["UTC"]
myMap := map[string]Point{"origin": {x: 0, y: 0}}
myMap["origin"].x = 3 // 是错误的。cannot assign to struct field .. in map
myMap := map[string]*Point{"origin": {x: 0, y: 0}}
myMap["origin"].x = 1 // 是可以的
runtime.GC()
name := "/path/to/file"
data, _ := ioutil.ReadFile(name)
myMap[name] = data[:10] // Bad:data 不会被回收
myMap[name] = append([]byte{}, data[:10]...) // Good:data 会被回收
展开
展开
Go 中没有集合,可以用 map 实现,并用struct{} 作为值,因为它被编译器优化过,指向同一个内存地址,不额外占空间。
type MySet map[int]struct{}
func (s MySet) Add(num int) {
if s == nil {
s = make(MySet)
}
s[num] = struct{}{}
}
set := MySet{}
set.Add(1)
展开
if r, ok := dst.(ReaderFrom); ok {
return r.ReadFrom(src)
}
展开
for init; condition; post {}
// 相当于 while
for condition {}
// 相当于 for(;;)
for {}
// 可以这样初始化、改变多个变量,但是不能像 C++ 里用`,`划分多个语句。
for i, j := 0, len(a) - 1; i < j; i, j = i+1, j-1 {
a[i], a[j] = a[j], a[i]
}
// 遍历的是 key
for x := range myMap {}
// 遍历的是 value
for _, v := range myMap {}
// 遍历的是 index
for x := range mySlice {}
// 遍历的是 value
for _, v := range mySlice {}
switch
展开
func unhex(c byte) byte {
switch {
case '0' <= c && c <= '9':
return c - '0'
case 'a' <= c && c <= 'f':
return c - 'a' + 10
case 'A' <= c && c <= 'F':
return c - 'A' + 10
}
return 0
}
fallthrough
关键字,或者switch c {
case ' ', '?', '&':
f(c)
}
Loop:
for {
r, size := decode(s[i:])
switch {
case size == 1 && r == invalidMsg:
return "", fmt.Errorf("invalid: %q", s) // %q 带双引号
case size == 0:
// 跳出 for 循环
break Loop
default:
result += r
}
i += size
}
func f(x int) interface{} {
switch x {
case 1:
return 1
case 2:
return "1"
}
return nil
}
t = f(1)
switch t := t.(type) {
default:
fmt.Printf("unexpected type: %T\n", t)
case int:
fmt.Printf("integer %d\n", t)
case string:
fmt.Printf("string %s\n", t)
}
}
展开
展开
多个返回值需要用括号括起来。 返回值可以有名字,初始值为类型的零值。return 可后面不加内容。
func Cut(s, sep []byte) (before, after []byte, found bool) {
if i := Index(s, sep); i >= 0 {
return s[:i], s[i+len(sep):], true
}
return s, nil, false
}
展开
展开
func adder() func(int) int {
sum := 0
return func(x int) int {
sum += x
return sum
}
}
pos, neg = adder(), adder()
for i := 0; i < 10; i++ {
fmt.Println(pos(i), net(-i))
}
展开
for i := 0; i < 100; i++ {
go func() {
fmt.Println(i)
}()
}
select{} // 阻塞
会得到100 个 0-100 中的任意数字。应该改为
go func(num int) {
fmt.Println(num)
}(i) // 将变量拷贝传进函数
会得到 0-100 的某个排列
另一种方法是
for i := 0; i < 100; i++ {
ii := i // 局部变量逃逸,指的是编译器会根据实际使用域决定放堆上还是栈上。这里会放到堆上。
go func() {
fmt.Println(ii)
}()
}
展开
展开
// Contents returns the file's contents as a string.
func Contents(filename string) (string, error) {
f, err := os.Open(filename)
if err != nil {
return "", err
}
defer f.Close() // Close 应该放到 err 判断后面,否则会 panic
var result []byte
buf := make([]byte, 100)
for {
n, err := f.Read(buf[0:])
result = append(result, buf[0:n]...) // append is discussed later.
if err != nil {
if err == io.EOF {
break
}
return "", err // f will be closed if we return here.
}
}
return string(result), nil // f will be closed if we return here.
}
展开
func f() {
startedAt := time.Now()
// 这样会立刻计算出函数用到的参数并进行拷贝,而不是执行 defer 时才计算。
defer fmt.Println("假执行时间: ", time.Since(startedAt))
// 利用闭包。这样拷贝的是函数指针。退出函数 f 时才计算。
defer func() { fmt.Println("真执行时间: ", time.Since(startedAt)) }()
time.Sleep(time.Second)
}
展开
func f() {
for {
func(..) {
row, err := db.Query("...")
if err != nil {
..
}
defer row.Close() // 这样会在内层函数退出时就执行
..
}(..)
}
}
展开
func compute(f func(float64, float64) float64) float64 {
return f(3, 4)
}
add := func(x, y float64) float64 {
return math.Sqrt(x*x + y*y)
}
compute(add)
展开
// slice 的初始化,会有一个容量是 cap,有 len 个 0 (int 的零值)的 int 数组。
s := make([]int, len, cap)
// len 和 cap 相等时可以忽略 cap,这样更简洁
s := make([]int, len)
// map 的初始化
m := make(map[string]string, cap)
展开
// append slice。数组不能 append。
func append(slice []T, elements ...T) []T
// 可以 append 多个
s = append(s, 0, 1, 2)
// append 后 len 就是原来的 len 加上新元素个数。
// 扩容逻辑:cap < 1024时,会翻倍增长,否则 1.25 倍。
var s []int
s = append(s, 0) // len 是 1, cap 是 1
s = append(s, 1) // len 是 2, cap 是 2
s = append(s, 2) // len 是 3, cap 是 4
fmt.Println(s) // [0, 1, 2]
func modifySlice(s []int) {
s = append(s, 3)
s[0] = -1
}
// 函数都是传值的,slice 的数据结构里包含指向数组的指针、len、cap。
modifySlice(s)
fmt.Println(s) // [-1, 1, 2],append 修改了 cap 和 len 不会作用在这里的 s
展开
// 不修改函数接收者时,用值作为函数接收者
func (r Response) Code() int {
return r.code
}
// 修改时,用指针。但是有时为了统一写法,就都用指针。
func (r *Response) SetCode(code int) {
r.code = code
}
// 使用值接收者的函数可以被指针、值调用。而指针接收者只能被指针调用。
var r *Response
r.SetCode(1)
r.Code()
type Point struct {
x, y int
}
func (p *Point) String() string {
return fmt.Sprintf("(%d, %d)", p.x, p.y)
}
myMap := map[string]*Point{"origin": {x: 0, y: 0}}
fmt.Printf("%s", myMap)
展开 1. 定义接口
type Writer interface {
}
如下是实现 sort.Interface 接口,需要实现 Len(), Less(), Swap() 函数
type Sequence []int
// Methods required by sort.Interface.
func (s Sequence) Len() int {
return len(s)
}
func (s Sequence) Less(i, j int) bool {
return s[i] < s[j]
}
func (s Sequence) Swap(i, j int) {
s[i], s[j] = s[j], s[i]
}
// Copy returns a copy of the Sequence.
func (s Sequence) Copy() Sequence {
copy := make(Sequence, 0, len(s))
return append(copy, s...)
}
// Method for printing - sorts the elements before printing.
func (s Sequence) String() string {
s = s.Copy() // Make a copy; don't overwrite argument.
sort.Sort(s)
// 也可以直接 sort.IntSlice(s).Sort(),就不用自己实现接口了。
return fmt.Sprint([]int(s))
}
扫码关注腾讯云开发者
领取腾讯云代金券
Copyright © 2013 - 2025 Tencent Cloud. All Rights Reserved. 腾讯云 版权所有
深圳市腾讯计算机系统有限公司 ICP备案/许可证号:粤B2-20090059 深公网安备号 44030502008569
腾讯云计算(北京)有限责任公司 京ICP证150476号 | 京ICP备11018762号 | 京公网安备号11010802020287
Copyright © 2013 - 2025 Tencent Cloud.
All Rights Reserved. 腾讯云 版权所有