Skip to content

Commit

Permalink
tip(go/go-learn): up
Browse files Browse the repository at this point in the history
  • Loading branch information
TIGERB committed Dec 11, 2021
1 parent 4c8da62 commit 25da062
Show file tree
Hide file tree
Showing 7 changed files with 253 additions and 132 deletions.
250 changes: 165 additions & 85 deletions go/go-learn/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,137 @@ cap当前切片的容量
- 「当前切片长度」小于1024 则扩容「当前容量的值」的两倍
- 「当前切片长度」大于1024 则持续扩容「当前切片容量的值」的1/4 直到 「当前切片容量的值」大于0 且「当前切片容量的值」大于「切片期望的容量的值」

```go
// go/src/runtime/slice.go
//
// growslice handles slice growth during append.
// It is passed the slice element type, the old slice, and the desired new minimum capacity,
// and it returns a new slice with at least that capacity, with the old data
// copied into it.
// The new slice's length is set to the old slice's length,
// NOT to the new requested capacity.
// This is for codegen convenience. The old slice's length is used immediately
// to calculate where to write new values during an append.
// TODO: When the old backend is gone, reconsider this decision.
// The SSA backend might prefer the new length or to return only ptr/cap and save stack space.
func growslice(et *_type, old slice, cap int) slice {
if raceenabled {
callerpc := getcallerpc()
racereadrangepc(old.array, uintptr(old.len*int(et.size)), callerpc, funcPC(growslice))
}
if msanenabled {
msanread(old.array, uintptr(old.len*int(et.size)))
}

if cap < old.cap {
panic(errorString("growslice: cap out of range"))
}

if et.size == 0 {
// append should not create a slice with nil pointer but non-zero len.
// We assume that append doesn't need to preserve old.array in this case.
return slice{unsafe.Pointer(&zerobase), old.len, cap}
}

newcap := old.cap
doublecap := newcap + newcap
if cap > doublecap {
newcap = cap
} else {
if old.len < 1024 {
newcap = doublecap
} else {
// Check 0 < newcap to detect overflow
// and prevent an infinite loop.
for 0 < newcap && newcap < cap {
newcap += newcap / 4
}
// Set newcap to the requested cap when
// the newcap calculation overflowed.
if newcap <= 0 {
newcap = cap
}
}
}

var overflow bool
var lenmem, newlenmem, capmem uintptr
// Specialize for common values of et.size.
// For 1 we don't need any division/multiplication.
// For sys.PtrSize, compiler will optimize division/multiplication into a shift by a constant.
// For powers of 2, use a variable shift.
switch {
case et.size == 1:
lenmem = uintptr(old.len)
newlenmem = uintptr(cap)
capmem = roundupsize(uintptr(newcap))
overflow = uintptr(newcap) > maxAlloc
newcap = int(capmem)
case et.size == sys.PtrSize:
lenmem = uintptr(old.len) * sys.PtrSize
newlenmem = uintptr(cap) * sys.PtrSize
capmem = roundupsize(uintptr(newcap) * sys.PtrSize)
overflow = uintptr(newcap) > maxAlloc/sys.PtrSize
newcap = int(capmem / sys.PtrSize)
case isPowerOfTwo(et.size):
var shift uintptr
if sys.PtrSize == 8 {
// Mask shift for better code generation.
shift = uintptr(sys.Ctz64(uint64(et.size))) & 63
} else {
shift = uintptr(sys.Ctz32(uint32(et.size))) & 31
}
lenmem = uintptr(old.len) << shift
newlenmem = uintptr(cap) << shift
capmem = roundupsize(uintptr(newcap) << shift)
overflow = uintptr(newcap) > (maxAlloc >> shift)
newcap = int(capmem >> shift)
default:
lenmem = uintptr(old.len) * et.size
newlenmem = uintptr(cap) * et.size
capmem, overflow = math.MulUintptr(et.size, uintptr(newcap))
capmem = roundupsize(capmem)
newcap = int(capmem / et.size)
}

// The check of overflow in addition to capmem > maxAlloc is needed
// to prevent an overflow which can be used to trigger a segfault
// on 32bit architectures with this example program:
//
// type T [1<<27 + 1]int64
//
// var d T
// var s []T
//
// func main() {
// s = append(s, d, d, d, d)
// print(len(s), "\n")
// }
if overflow || capmem > maxAlloc {
panic(errorString("growslice: cap out of range"))
}

var p unsafe.Pointer
if et.ptrdata == 0 {
p = mallocgc(capmem, nil, false)
// The append() that calls growslice is going to overwrite from old.len to cap (which will be the new length).
// Only clear the part that will not be overwritten.
memclrNoHeapPointers(add(p, newlenmem), capmem-newlenmem)
} else {
// Note: can't use rawmem (which avoids zeroing of memory), because then GC can scan uninitialized memory.
p = mallocgc(capmem, et, true)
if lenmem > 0 && writeBarrier.enabled {
// Only shade the pointers in old.array since we know the destination slice p
// only contains nil pointers because it has been cleared during alloc.
bulkBarrierPreWriteSrcOnly(uintptr(p), uintptr(old.array), lenmem-et.size+et.ptrdata)
}
}
memmove(p, old.array, lenmem)

return slice{p, old.len, newcap}
}
```

## uintptr unsafe.Pointer

uintptr 指针 可计算偏移量
Expand All @@ -121,6 +252,7 @@ fmt.Println("d.PropertyTwo", d.PropertyTwo)

> 参考 https://www.flysnow.org/2017/07/06/go-in-action-unsafe-pointer.html

## Map

数组->数组
Expand Down Expand Up @@ -217,113 +349,61 @@ page 8kb

---

> 栈内存在哪?
- 什么是堆和栈,它们在哪儿?

---

> Go垃圾回收
- Garbage Collection In Go : Part I - Semantics https://www.ardanlabs.com/blog/2018/12/garbage-collection-in-go-part1-semantics.html
- Garbage Collection In Go : Part II - GC Traces https://www.ardanlabs.com/blog/2019/05/garbage-collection-in-go-part2-gctraces.html
- Garbage Collection In Go : Part III - GC Pacing https://www.ardanlabs.com/blog/2019/07/garbage-collection-in-go-part3-gcpacing.html



# 逃逸分析

- golang 逃逸分析详解 https://zhuanlan.zhihu.com/p/91559562

# 垃圾回收

1. Go语言垃圾回收:
- 回收的内存一部分是栈上逃逸到堆上的对象占用的内存
- 堆上的大对象

2. 栈内存和堆内存都来自于Go的内存分配器。

3. Go的内存分配器分别维护两种标识的内存(span),一种包含指针(堆内存),一种不包含指针的(栈内存或者堆内存)。

根对象到底是什么? https://www.bookstack.cn/read/qcrao-Go-Questions/spilt.2.GC-GC.md

```
- 全局变量
- 栈逃逸到堆上的变量
- ?
```

> 栈内存在哪?
- 什么是堆和栈,它们在哪儿?

- 为什么寄存器比内存快?http://www.ruanyifeng.com/blog/2013/10/register.html

---

> Go垃圾回收
- Garbage Collection In Go : Part I - Semantics https://www.ardanlabs.com/blog/2018/12/garbage-collection-in-go-part1-semantics.html
- Garbage Collection In Go : Part II - GC Traces https://www.ardanlabs.com/blog/2019/05/garbage-collection-in-go-part2-gctraces.html
- Garbage Collection In Go : Part III - GC Pacing https://www.ardanlabs.com/blog/2019/07/garbage-collection-in-go-part3-gcpacing.html

# k8s

```
1. 目录隔离 chroot 视图级别的隔离
2. 进程在资源的视图上隔离 namespace
3. 限制资源使用率 cgroup
```

# 服务发现

```
nginx
confd
etcd
```




























































74041843

# 牛年到,提前给大家拜年发红包了~~~

关注我的个人技术公众号(搜索公众号**tigerbcode**或者扫下方二维码关注) 回复关键字【**牛犇牛**】获取支付宝红包口令领取现金红包

🐂

最后在这里感谢2020这一年来大家的支持,新的牛年继续和大家一起互相学习,预祝大家:

# 牛年大吉!!!

![https://p6-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/5f8f021eb2934b60af98089ca2a22942~tplv-k3u1fbpfcp-watermark.image](https://p6-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/5f8f021eb2934b60af98089ca2a22942~tplv-k3u1fbpfcp-watermark.image)

- Etcd、Confd 、Nginx 服务发现 https://www.chenshaowen.com/blog/service-discovery-etcd-confd-nginx.html

15 changes: 15 additions & 0 deletions go/go-learn/experience/phper2gopher.md
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,21 @@ closure(闭包)|`$varClosure = function() {};`|`var varClosure func() = func() {
channel|无|`var varChannel chan string = make(chan string)` 无缓存channel;<br>`var varChannelBuffer chan string = make(chan string, 6)`有缓存channel

### 常用函数对比

常用函数描述 | PHP | Go
--------|--------|--------
数组长度 | count() | len()
分割字符串为数组 | explode() | strings.Split(s string, sep string) []string
转大写 | strtoupper() | strings.ToUpper(s string) string
转小写 | strtolower() | strings.ToLower(s string) string
去除空格 | trim() | strings.Trim(s, cutset string) string
json序列化 | json_encode() | json.Marshal(v interface{}) ([]byte, error)
json反序列化 | json_decode() | json.Unmarshal(data []byte, v interface{}) error
序列化(不再建议使用) | serialize()、unserialize() | 包https://github.com/wulijun/go-php-serialize
md5 | md5() | 包crypto/md5
终端输出 | echo、var_dump等 | fmt.Println(a ...interface{})
各种类型互转 | intval()等 | 包strconv

### PHP类的实例化和Go结构体的初始化的对比

PHP类的实例化
Expand Down
Binary file removed go/go-learn/main
Binary file not shown.
48 changes: 26 additions & 22 deletions go/go-learn/main.go
Original file line number Diff line number Diff line change
@@ -1,31 +1,35 @@
package main

import (
"fmt"
"unsafe"
// 导入net/http包
"net/http"
"os"
"runtime/trace"
)

type flightGroup interface {
// Done is called when Do is done.
Do(key string, fn func() (interface{}, error)) (interface{}, error)
}

// golangci-lint run --disable-all -E maligned
func main() {
//创建trace文件
f, err := os.Create("trace.out")
if err != nil {
panic(err)
}

type Demo struct {
A int8
B int64
C int8
}
defer f.Close()

type DemoTwo struct {
A int8
C int8
B int64
}
//启动trace goroutine
err = trace.Start(f)
if err != nil {
panic(err)
}
defer trace.Stop()

func main() {
demo := Demo{}
demoTwo := DemoTwo{}
fmt.Println(unsafe.Sizeof(demo), unsafe.Sizeof(demoTwo))
// ------------------ 使用http包启动一个http服务 方式一 ------------------
// *http.Request http请求内容实例的指针
// http.ResponseWriter 写http响应内容的实例
http.HandleFunc("/v1/demo", func(w http.ResponseWriter, r *http.Request) {
// 写入响应内容
w.Write([]byte("Hello TIGERB !\n"))
})
// 启动一个http服务并监听8888端口 这里第二个参数可以指定handler
http.ListenAndServe(":8888", nil)
}
Binary file removed go/go-learn/main.o
Binary file not shown.
Binary file added go/go-learn/trace.out
Binary file not shown.
Loading

0 comments on commit 25da062

Please sign in to comment.