-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathindex.html
20 lines (20 loc) · 17.5 KB
/
index.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<!doctype html><html lang=zh dir=auto><head><meta name=generator content="Hugo 0.142.0"><meta charset=utf-8><meta http-equiv=X-UA-Compatible content="IE=edge"><meta name=viewport content="width=device-width,initial-scale=1,shrink-to-fit=no"><meta name=robots content="index, follow"><link rel=stylesheet href=https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css integrity=sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm crossorigin=anonymous><script src=https://code.jquery.com/jquery-3.2.1.slim.min.js integrity=sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN crossorigin=anonymous></script><script src=https://cdn.jsdelivr.net/npm/[email protected]/dist/umd/popper.min.js integrity=sha384-ApNbgh9B+Y1QKtv3Rn7W3mgPxhU9K/ScQsAP7hUibX39j7fakFPskvXusvfa0b4Q crossorigin=anonymous></script><script src=https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.min.js integrity=sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5+76PVCmYl crossorigin=anonymous></script><title>握月担风</title>
<meta name=keywords content="Blog,Portfolio,PaperMod"><meta name=description content="0.0"><meta name=author content="ivan"><link rel=canonical href=https://www.yici.xin/><meta name=google-site-verification content="XYZabc"><meta name=yandex-verification content="XYZabc"><meta name=msvalidate.01 content="XYZabc"><link crossorigin=anonymous href=/assets/css/stylesheet.278e8b2dd0edae6a4a4d865210e46385ee100556bcf14ba56506e7501326056e.css integrity="sha256-J46LLdDtrmpKTYZSEORjhe4QBVa88UulZQbnUBMmBW4=" rel="preload stylesheet" as=style><script defer crossorigin=anonymous src=/js/extended.js></script><link rel=icon href=https://yicixin-blog-image.oss-accelerate.aliyuncs.com/img/202211171234877.jpg><link rel=icon type=image/png sizes=16x16 href=https://yicixin-blog-image.oss-accelerate.aliyuncs.com/img/202211171234877.jpg><link rel=icon type=image/png sizes=32x32 href=https://yicixin-blog-image.oss-accelerate.aliyuncs.com/img/202211171234877.jpg><link rel=apple-touch-icon href=https://yicixin-blog-image.oss-accelerate.aliyuncs.com/img/202211171234877.jpg><link rel=mask-icon href=https://yicixin-blog-image.oss-accelerate.aliyuncs.com/img/202211171234877.jpg><meta name=theme-color content="#2e2e33"><meta name=msapplication-TileColor content="#2e2e33"><link rel=alternate type=application/rss+xml href=https://www.yici.xin/index.xml><link rel=alternate hreflang=zh href=https://www.yici.xin/><noscript><style>#theme-toggle,.top-link{display:none}</style><style>@media(prefers-color-scheme:dark){:root{--theme:rgb(29, 30, 32);--entry:rgb(46, 46, 51);--primary:rgb(218, 218, 219);--secondary:rgb(155, 156, 157);--tertiary:rgb(65, 66, 68);--content:rgb(196, 196, 197);--hljs-bg:rgb(46, 46, 51);--code-bg:rgb(55, 56, 62);--border:rgb(51, 51, 51)}.list{background:var(--theme)}.list:not(.dark)::-webkit-scrollbar-track{background:0 0}.list:not(.dark)::-webkit-scrollbar-thumb{border-color:var(--theme)}}</style></noscript><link rel=stylesheet href=https://cdn.jsdelivr.net/npm/[email protected]/style.css><meta property="og:title" content="握月担风"><meta property="og:description" content="0.0"><meta property="og:type" content="website"><meta property="og:url" content="https://www.yici.xin/"><meta property="og:image" content="https://www.yici.xin/%3Clink%20or%20path%20of%20image%20for%20opengraph,%20twitter-cards%3E"><meta name=twitter:card content="summary_large_image"><meta name=twitter:image content="https://www.yici.xin/%3Clink%20or%20path%20of%20image%20for%20opengraph,%20twitter-cards%3E"><meta name=twitter:title content="握月担风"><meta name=twitter:description content="0.0"><script type=application/ld+json>{"@context":"https://schema.org","@type":"Organization","name":"握月担风","url":"https://www.yici.xin/","description":"0.0","thumbnailUrl":"https://yicixin-blog-image.oss-accelerate.aliyuncs.com/img/202211171234877.jpg","sameAs":["https://github.com/yicixin","mailto:[email protected]"]}</script></head><body class=list id=top><script>localStorage.getItem("pref-theme")==="dark"?document.body.classList.add("dark"):localStorage.getItem("pref-theme")==="light"?document.body.classList.remove("dark"):window.matchMedia("(prefers-color-scheme: dark)").matches&&document.body.classList.add("dark")</script><header class=header><nav class=nav><div class=logo><a href=https://www.yici.xin/ accesskey=h title="握月担风 (Alt + H)">握月担风</a><div class=logo-switches><button id=theme-toggle accesskey=t title="(Alt + T)"><svg id="moon" width="24" height="18" viewBox="0 0 24 24" fill="none" stroke="currentcolor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 12.79A9 9 0 1111.21 3 7 7 0 0021 12.79z"/></svg><svg id="sun" width="24" height="18" viewBox="0 0 24 24" fill="none" stroke="currentcolor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="5"/><line x1="12" y1="1" x2="12" y2="3"/><line x1="12" y1="21" x2="12" y2="23"/><line x1="4.22" y1="4.22" x2="5.64" y2="5.64"/><line x1="18.36" y1="18.36" x2="19.78" y2="19.78"/><line x1="1" y1="12" x2="3" y2="12"/><line x1="21" y1="12" x2="23" y2="12"/><line x1="4.22" y1="19.78" x2="5.64" y2="18.36"/><line x1="18.36" y1="5.64" x2="19.78" y2="4.22"/></svg></button><ul class=lang-switch><li></li></ul></div></div><ul id=menu><li><a href=https://www.yici.xin/tags/ title=标签🏷️><span>标签🏷️</span></a></li></ul></nav></header><main class=main><article class="first-entry home-info"><header class=entry-header><h1></h1></header><div class=entry-content>纸上得来终觉浅…</div><footer class=entry-footer><div class=social-icons><a href=https://github.com/yicixin target=_blank rel="noopener noreferrer me" title=Github><svg viewBox="0 0 24 24" fill="none" stroke="currentcolor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M9 19c-5 1.5-5-2.5-7-3m14 6v-3.87a3.37 3.37.0 00-.94-2.61c3.14-.35 6.44-1.54 6.44-7A5.44 5.44.0 0020 4.77 5.07 5.07.0 0019.91 1S18.73.65 16 2.48a13.38 13.38.0 00-7 0C6.27.65 5.09 1 5.09 1A5.07 5.07.0 005 4.77 5.44 5.44.0 003.5 8.55c0 5.42 3.3 6.61 6.44 7A3.37 3.37.0 009 18.13V22"/></svg>
</a><a href=mailto:[email protected] target=_blank rel="noopener noreferrer me" title=Email><svg viewBox="0 0 24 21" fill="none" stroke="currentcolor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M4 4h16c1.1.0 2 .9 2 2v12c0 1.1-.9 2-2 2H4c-1.1.0-2-.9-2-2V6c0-1.1.9-2 2-2z"/><polyline points="22,6 12,13 2,6"/></svg></a></div></footer></article><article class=post-entry><div class=post-info><header class=entry-header><h2>转换bytes和string的最佳实践</h2></header><section class=entry-content><p>本文golang源码为1.18版本
标准转换 使用标准转换是最常见的选择
package main func main() { s := "Hello, world!" // string转byte数组 b := []byte(s) // byte数组转string s2 := string(b) } 该转换语句会被go编译器翻译为runtime层的方法调用,其中[]byte到string的转换对应/src/runtime/string.go:81处的slicebytetostring函数;而string到[]byte的转换对应的则是/src/runtime/string.go:172处的stringtoslicebyte函数。
先来看看比较简单的stringtoslicebyte函数,tmpBuf类型是个大小为32的byte数组。
// The constant is known to the compiler. // There is no fundamental theory behind this number. 🤣 const tmpStringBufSize = 32 type tmpBuf [tmpStringBufSize]byte func stringtoslicebyte(buf *tmpBuf, s string) []byte { var b []byte if buf != nil && len(s) <= len(buf) { *buf = tmpBuf{} b = buf[:len(s)] } else { // 如果没有缓冲区或缓冲区大小不足,需要申请内存 b = rawbyteslice(len(s)) } // 复制数据 copy(b, s) return b } func rawbyteslice(size int) (b []byte) { // 容量计算,考虑内存对齐,寻找大小最匹配的内存块 cap := roundupsize(uintptr(size)) // 使用mallocgc申请对应大小的内存 p := mallocgc(cap, nil, false) // 如果要申请的size和最终计算得到的cap大小不一致,cap只会比size更大,清理掉多余的内存 if cap != uintptr(size) { memclrNoHeapPointers(add(p, uintptr(size)), cap-uintptr(size)) } // 将b指向这片申请好的内存。该slice不为空,故外部使用copy进行覆盖而不是append *(*slice)(unsafe.Pointer(&b)) = slice{p, size, int(cap)} return } 当需要转换的字符串长度小于32时,只会进行内存复制,而大于32的话,除了复制操作,还需要分配内存。
...</p></section><footer class=entry-footer><span title='2023-02-01 19:34:04 +0800 +0800'>2023-02-01</span> · 壹次心</footer></div><a class=entry-link aria-label="post link to 转换bytes和string的最佳实践" href=https://www.yici.xin/post/tech/%E8%BD%AC%E6%8D%A2bytes%E5%92%8Cstring%E7%9A%84%E6%9C%80%E4%BD%B3%E5%AE%9E%E8%B7%B5/></a></article><article class=post-entry><div class=post-info><header class=entry-header><h2>Golang-map的操作</h2></header><section class=entry-content><p>创建 map 创建 map 的语法很简单
// 不指定map长度 ageMp := make(map[string]int) // 指定map长度 ageMp := make(map[string]int, 8) // ageMp 为 nil,不能向其添加元素,会直接panic var ageMp map[string]int 通过汇编语言,我们能够跟踪到 map 的创建最终会调用 runtime.makemap 方法
// makemap implements Go map creation for make(map[k]v, hint). // If the compiler has determined that the map or the first bucket // can be created on the stack, h and/or bucket may be non-nil. // If h != nil, the map can be created directly in h. // If h.buckets != nil, bucket pointed to can be used as the first bucket. // 翻译:makemap实现了make(map[k]v, hint)这种形式语法的Go map创建。 // 如果编译器已经确定该map或者第一个bucket能够在这个栈上创建,那么h和(或)bucket可能为非nil。 // 如果h不是nil,那么该map能直接创建在这个h上。 // 如果h.buckets不是nil, 则被指向的bucket能被用来做第一个bucket func makemap(t *maptype, hint int, h *hmap) *hmap { // 计算指定的大小所需要的内容是否超出出系统允许的最大分配大小 mem, overflow := math.MulUintptr(uintptr(hint), t.bucket.size) if overflow || mem > maxAlloc { hint = 0 } // 初始化hmap,并指定随机种子 if h == nil { h = new(hmap) } h.hash0 = fastrand() // Find the size parameter B which will hold the requested # of elements. // For hint < 0 overLoadFactor returns false since hint < bucketCnt. // 通过overLoadFactor(hint, B)函数找到一个能装下指定map大小个元素个数的最小B,要满足 装载因子*2^B < hint B := uint8(0) for overLoadFactor(hint, B) { B++ } h.B = B // allocate initial hash table // if B == 0, the buckets field is allocated lazily later (in mapassign) // If hint is large zeroing this memory could take a while. // 开始对hash table进行初始化。如果B==0则buckets 进行懒初始化操作(赋值的时候才进行初始化),如果B值特别大,则初始化需要一段时间,主要通过 makeBucketArray() 函数实现 if h.B != 0 { var nextOverflow *bmap h.buckets, nextOverflow = makeBucketArray(t, h.B, nil) if nextOverflow != nil { h.extra = new(mapextra) // 溢出桶地址赋值 h.extra.nextOverflow = nextOverflow } } return h } // makeBucketArray initializes a backing array for map buckets. // 1<<b is the minimum number of buckets to allocate. // dirtyalloc should either be nil or a bucket array previously // allocated by makeBucketArray with the same t and b parameters. // If dirtyalloc is nil a new backing array will be alloced and // otherwise dirtyalloc will be cleared and reused as backing array. // 翻译:makeBucketArray为map buckets初始化一个备用数组 // 2^b是该buckets长度的最小值 // dirtyalloc之前应该是nil或者bucket数组 // 如果dirtyalloc 为nil,将分配一个新的后备数组,否则将清除dirtyalloc 并作为后备数组重用。 func makeBucketArray(t *maptype, b uint8, dirtyalloc unsafe.Pointer) (buckets unsafe.Pointer, nextOverflow *bmap) { base := bucketShift(b) // base = 2^b nbuckets := base // For small b, overflow buckets are unlikely. // Avoid the overhead of the calculation. // 对于小的b,不太可能会需要溢出桶,可以避免这部分计算开销 // 对于b>4(桶的数量> 2^4)的话,则需要创建2^(b-4)个溢出桶。 if b >= 4 { // 加上溢出桶的数量 nbuckets += bucketShift(b - 4) // 总大小 sz := t.bucket.size * nbuckets // 针对所需要的内存大小,mallocgc将分配的内存块大小 up := roundupsize(sz) if up != sz { // 如果总大小和mallocgc将分配的内存块大小不同,以mallocgc分配的为准,计算nbuckets nbuckets = up / t.bucket.size } } if dirtyalloc == nil { buckets = newarray(t.bucket, int(nbuckets)) } else { // dirtyalloc was previously generated by // the above newarray(t.bucket, int(nbuckets)) // but may not be empty. buckets = dirtyalloc size := t.bucket.size * nbuckets if t.bucket.ptrdata != 0 { memclrHasPointers(buckets, size) } else { memclrNoHeapPointers(buckets, size) } } if base != nbuckets { // We preallocated some overflow buckets. // To keep the overhead of tracking these overflow buckets to a minimum, // we use the convention that if a preallocated overflow bucket's overflow // pointer is nil, then there are more available by bumping the pointer. // We need a safe non-nil pointer for the last overflow bucket; just use buckets. // 我们提前分配了一些溢出桶,为了使得追踪溢出桶的开销最小,我们这样约定: // 如果溢出桶的overflow指针为nil,那么代表还有空间在出现哈希碰撞时使用, // 溢出桶的最后一个桶的overflow需要指向一个安全的非空指针,这里指向了buckets的第一个桶 // 具体的用处在map写入时,需要创建溢出桶时会用到,具体在newoverflow函数中 nextOverflow = (*bmap)(add(buckets, base*uintptr(t.bucketsize))) // 指向第一个溢出桶 last := (*bmap)(add(buckets, (nbuckets-1)*uintptr(t.bucketsize))) // 指向最后一个溢出桶 last.setoverflow(t, (*bmap)(buckets)) // 溢出桶的最后一个桶的overflow指向了buckets的第一个桶 } return buckets, nextOverflow } 从上面代码可以得知,2^B 并不等于 buckets 的大小,它只是创建 buckets 时的 base 部分,在该部分后,还有溢出桶。所以正常桶和溢出桶在内存上的分布是连续的,溢出桶的指针记录在了 hmap 的 extra 字段中。
...</p></section><footer class=entry-footer><span title='2022-12-30 10:49:41 +0800 +0800'>2022-12-30</span> · 壹次心</footer></div><a class=entry-link aria-label="post link to Golang-map的操作" href=https://www.yici.xin/post/tech/golang-map%E7%9A%84%E6%93%8D%E4%BD%9C/></a></article><article class=post-entry><div class=post-info><header class=entry-header><h2>如何在Keynote中贴出好看的代码</h2></header><section class=entry-content><p>brew install highlight 需要安装highlight工具。
用法:
转化剪贴板中的代码:
pbpaste | highlight --syntax=go --style=github -k "Fira Code" -K 36 -u "utf-8" -t 4 -O rtf | pbcopy --syntax指定代码语法格式,-u指定编码,否则中文会乱码,--style指定高亮的样式,-K指定代码的字大小,rtf是要转出的格式,还可以是其他的如html。
转化代码文件:
highlight --style=github -k "Fira Code" -K 36 -u "utf-8" -t 4 -O rtf hello.go | pbcopy</p></section><footer class=entry-footer><span title='2022-12-27 18:30:01 +0800 +0800'>2022-12-27</span> · 壹次心</footer></div><figure class=entry-cover><img loading=lazy src=https://yicixin-blog-image.oss-accelerate.aliyuncs.com/img/202212271832751.png alt=在keynote中展示格式化的代码></figure><a class=entry-link aria-label="post link to 如何在Keynote中贴出好看的代码" href=https://www.yici.xin/post/tech/keynote%E4%B8%AD%E8%B4%B4%E4%BB%A3%E7%A0%81/></a></article><footer class=page-footer><nav class=pagination><a class=next href=https://www.yici.xin/page/2/>下一页 »</a></nav></footer></main><footer class=footer><span>© 2025 <a href=https://www.yici.xin/>握月担风</a></span>
<span>Powered by
<a href=https://gohugo.io/ rel="noopener noreferrer" target=_blank>Hugo</a> &
<a href=https://github.com/adityatelange/hugo-PaperMod/ rel=noopener target=_blank>PaperMod</a></span></footer><a href=#top aria-label="go to top" title="Go to Top (Alt + G)" class=top-link id=top-link accesskey=g><svg viewBox="0 0 12 6" fill="currentcolor"><path d="M12 6H0l6-6z"/></svg>
</a><script>let menu=document.getElementById("menu");menu&&(menu.scrollLeft=localStorage.getItem("menu-scroll-position"),menu.onscroll=function(){localStorage.setItem("menu-scroll-position",menu.scrollLeft)}),document.querySelectorAll('a[href^="#"]').forEach(e=>{e.addEventListener("click",function(e){e.preventDefault();var t=this.getAttribute("href").substr(1);window.matchMedia("(prefers-reduced-motion: reduce)").matches?document.querySelector(`[id='${decodeURIComponent(t)}']`).scrollIntoView():document.querySelector(`[id='${decodeURIComponent(t)}']`).scrollIntoView({behavior:"smooth"}),t==="top"?history.replaceState(null,null," "):history.pushState(null,null,`#${t}`)})})</script><script>var mybutton=document.getElementById("top-link");window.onscroll=function(){document.body.scrollTop>800||document.documentElement.scrollTop>800?(mybutton.style.visibility="visible",mybutton.style.opacity="1"):(mybutton.style.visibility="hidden",mybutton.style.opacity="0")}</script><script>document.getElementById("theme-toggle").addEventListener("click",()=>{document.body.className.includes("dark")?(document.body.classList.remove("dark"),localStorage.setItem("pref-theme","light")):(document.body.classList.add("dark"),localStorage.setItem("pref-theme","dark"))})</script></body></html>