1. 引用传递时append会复制生成新的指针


package main
import ( "fmt" ) func w(s []int )[]int{ fmt.Printf("in w %v %#v ",s ,&s[] )
  //append后s指定新复制的内存指针了,不再指向原来的内存
s=append(s, )
fmt.Printf("after append w %v %#v ",s ,&s[] )
return s
} func main() {
s:=[]int{}
fmt.Printf("out of w %v %#v ",s ,&s[] )
s2:=w(s)
//原来的指针s的内容依然在内存中,而不是被覆盖/GC了
fmt.Printf("after w %v %#v %v %#v ",s ,&s[],s2 ,&s2[] )
}

output:

out of w [] (*int)(0x40e020) in w [] (*int)(0x40e020) after append w [ ] (*int)(0x40e040) after w [] (*int)(0x40e020) [ ] (*int)(0x40e040)

2. 空值append

package main

import (
"fmt"
) func main() {
s:=[][]int{}
//使用...更加方便,还不会导致塞入空值
fmt.Println("Hello, playground", append(s, [][]int{}... ), append(s, []int{} ))
}

output:

Hello, playground [] [[]]

3. 数组、slice、切片的雷!

package main

import (
"fmt"
"reflect"
) func main() {
//固定长度是array类型,可以覆盖成员,但不能修改长度,即不能append
a := []int{,}
a[]=
//没设置长度是slice类型,即动态或不定长数组, 也能覆盖成员,也修改长度,即支持append
s := []int{,}
//s[1:len(s):cap(s)] 等效 s[1:len(s)]
s[]=
//注意下村是:左开(含左边元素),右闭(不含右边元素)
fmt.Printf("%#v %#v %v %v %#v %#v %#v \n", a ,s, reflect.TypeOf(a).Kind(), reflect.TypeOf(s).Kind(), a[:len(a)], s[:len(s):cap(s)],s[:len(s)], ) //subslice切片
//切片,也叫subslice,是一块基于父slice的投影
subArray:=a[:]
//报错:invalid slice index: 3 > 2, 即len不能超过cap
//subArray2:=subArray[0:3:2]
subArray2:=subArray[::]
//报错:index out of range [1] with length 1
//subArray2[1]=222
//报错:index out of range [1] with length 1,len+offset>父slice的cap ,投影不能超出父slice的cap区域
//subArray3:=subArray2[1:2:2]
subArray3:=subArray2[:]
//切片是指定父slice的指针,所以会修改父slice,使用时一定要小心!!!
subArray3[]= //subArray虽然是新变量名,但实际指定同一个内存地址
fmt.Printf("subslice %#v %#v %#v %#v %v %v %v %v\n", subArray, a, subArray2,subArray3, &subArray[], &a[], &subArray2[],&subArray3[]) //扩容测试
fmt.Printf("%v %v \n", len(s), cap(s))
s=append(s, )
fmt.Printf("%v %v \n", len(s), cap(s))
s=append(s, )
fmt.Printf("%v %v \n", len(s), cap(s))
//tmp:=[8]int{}
//错误:cannot use tmp (type [8]int) as type []int in append
//正确玩法:
//不能用Printf中有unicode,否则会 format %扩 has unknown verb 扩
fmt.Println("len增加且超过cap时,若<=1024,以100%扩容 ")
s=[]int{}
i:=
for i>= {
fmt.Printf("%v %v \n", len(s), cap(s))
s=append(s,)
i-=
} fmt.Println("len增加且超过cap>1024时,否则以大约25%扩容,注意是大约")
//大约25%扩容详细参考: https://juejin.im/post/5ca4239ef265da30807fea48
i=
s=[]int{}
for i>= {
s=append(s,)
i-=
if i%=={
fmt.Printf("%v %v \n", len(s), cap(s))
}
} }

output:

[]int{, , , } []int{, } array slice []int{, , } []int{} []int{}
subslice []int{, } []int{, , , } []int{} []int{} 0x40e020 0x40e020 0x40e020 0x40e020 len增加且超过cap时,若<=,以100%扩容 len增加且超过cap>1024时,否则以大约25%扩容,注意是大约

4. 字符串不能随意for

package main

import (
"fmt"
) func main() {
s:="abc中国人" fmt.Println("for len是逐个unicode,也叫rune")
for k,v:=range s {
fmt.Println(k, string(v))
}
fmt.Println("for len是逐个字节, 非ascii就会乱")
for i:=;i<len(s);i++{
fmt.Println(i, string(s[i]))
}
fmt.Println("正确用法:")
//for len是逐个字节
u:=[]rune(s)
l:=len(u)
for i:=;i<l;i++{
fmt.Println(i, string(u[i]))
}
}

output:

for len是逐个unicode,也叫rune
a
b
c



for len是逐个字节, 非ascii就会乱
a
b
c
ä
¸
­
å
›
½
ä
º
º
正确用法:
a
b
c


4. map是无序的

package main

import (
"fmt"
) func main() {
m:=map[string]string{
"cc":"CC",
"aa":"AA",
"bb":"BB",
}
for k,v:=range(m){
fmt.Println(k,v)
}
fmt.Println("")
for k,v:=range(m){
fmt.Println(k,v)
}
fmt.Println("")
for k,v:=range(m){
fmt.Println(k,v)
}
fmt.Println("")
// sort 'string' key in increasing order
fmt.Println("fix : ")
for k,v:=range(m){
fmt.Println(k,v)
} }

output:

cc CC
aa AA
bb BB cc CC
aa AA
bb BB bb BB
cc CC
aa AA fix :
cc CC
aa AA
bb BB

原因:

根据Go规范, map上的迭代顺序是不确定的,并且在程序运行之间可能会有所不同。实际上,不仅它是不确定的,而且实际上是有意随机化的。这是因为它曾经是可预测的,并且Go语言开发人员不希望人们依赖未指定的行为,所以他们有意地将其随机化,因此不可能依赖此行为。维护原插入顺序需要更多内存和cpu操作,Go设计简洁,无序意味着性能更佳,且不是所有地方都需要顺序。想排序或者按插入顺序,很容易自行实现。在Go 1.12+中,您只需打印一个map,它将自动按键排序。之所以添加它,是因为它可以轻松测试map。

原文:https://blog.golang.org/go-maps-in-action  中  When iterating over a map with a range loop, the iteration order is not specified and is not guaranteed to be the same from one iteration to the next. If you require a stable iteration order you must maintain a separate data structure that specifies that order。

参考 : https://tip.golang.org/doc/go1.12#fmt

解决:package mainimport (    "fmt"    "sort"

)
//按插入的顺序
type RawSortedMap struct {
  //map key类型不能是slices, maps, and functions; these types cannot be compared using ==, and may not be used as map keys.
m map[string]interface{}
keys []interface{}
} func NewRawSortedMap(cap int)RawSortedMap{
m := make(map[string]interface{}, cap)
keys:=make([]interface{}, cap)
n:=RawSortedMap{m, keys}
return n
} func (r *RawSortedMap) Set(k string, v interface{}) {
//通过k 快速查找
  //map不能同时read 和write,否则请加sync.RWMutex锁或者CAS .
  r.m[k] = len(r.m)
//通过keys数组快速遍历
r.keys = append(r.keys, v)
}
func main() { m := make(map[int]string)
m[] = "a"
m[] = "c"
m[] = "b" // To store the keys in slice in sorted order
var keys []int
for k := range m {
keys = append(keys, k)
}
//按数字大小的顺序
sort.Ints(keys)
//按字母的顺序
//sort.Strings(keys) // To perform the opertion you want
for _, k := range keys {
fmt.Println("Key:", k, "Value:", m[k])
}
}

你不知道的Golang盲点汇总【持续更新】的更多相关文章

  1. 《WCF技术剖析》博文系列汇总[持续更新中]

    原文:<WCF技术剖析>博文系列汇总[持续更新中] 近半年以来,一直忙于我的第一本WCF专著<WCF技术剖析(卷1)>的写作,一直无暇管理自己的Blog.在<WCF技术剖 ...

  2. 中国.NET:各地微软技术俱乐部汇总(持续更新中...)

    中国.NET:各地微软技术俱乐部汇总(持续更新中...)   本文是转载文,源地址: https://www.cnblogs.com/panchun/p/JLBList.html by ​史记微软. ...

  3. redis日常使用汇总--持续更新

    redis日常使用汇总--持续更新 工作中有较多用到redis的场景,尤其是触及性能优化的方面,传统的缓存策略在处理持久化和多服务间数据共享的问题总是不尽人意,此时引入redis,但redis是单线程 ...

  4. 跟我学SpringCloud | 终篇:文章汇总(持续更新)

    SpringCloud系列教程 | 终篇:文章汇总(持续更新) 我为什么这些文章?一是巩固自己的知识,二是希望有更加开放和与人分享的心态,三是接受各位大神的批评指教,有任何问题可以联系我: inwsy ...

  5. 优步UBER司机全国各地最新奖励政策汇总(持续更新...)

    滴快车单单2.5倍,注册地址:http://www.udache.com/ 如何注册Uber司机(全国版最新最详细注册流程)/月入2万/不用抢单:http://didi-uber.com/archiv ...

  6. 痞子衡嵌入式:史上最强i.MX RT学习资源汇总(持续更新中...)

    大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是i.MX RT学习资源. 类别 资源 简介 官方汇总 i.MXRT产品主页 恩智浦官方i.MXRT产品主页,最权威的资料都在这里,参考手 ...

  7. IT书籍下载汇总--持续更新

    本书单由北北分享,并持续更新,请将该地址加入收藏夹:北北的书单 .badge{float:right;}.list-group-item > .badge + .badge{margin-rig ...

  8. Type Script在Visual Studio 2013中的问题汇总(持续更新…)

    TypeScript在vs2012下的问题 TypeScript对VS2012支持度比较低,建议升级为VS2013版本以上. 在VS2013中无法创建TypeScript项目 VS2013默认不支持T ...

  9. LeetCode All in One 题目讲解汇总(持续更新中...)

    终于将LeetCode的免费题刷完了,真是漫长的第一遍啊,估计很多题都忘的差不多了,这次开个题目汇总贴,并附上每道题目的解题连接,方便之后查阅吧~ 477 Total Hamming Distance ...

随机推荐

  1. php实现基础排序算法

    <?php header("content-type:text/html;charset=utf-8"); $testArr = array(); $time1 = micr ...

  2. 推荐一款适合Dynamics 365/Dynamics CRM 2016 使用的弹出窗插件AlertJs

    Github地址: https://github.com/PaulNieuwelaar/alertjs 目前有两个版本,3.0版本(30天免费试用)以及2.1版本(完全免费) ------------ ...

  3. DevOps 工程师成长日记系列四:打包

    原文地址:https://medium.com/@devfire/how-to-become-a-devops-engineer-in-six-months-or-less-part-4-packag ...

  4. [转]Eclipse插件开发之基础篇(5) 制作OSGi Bundle

    原文地址:http://www.cnblogs.com/liuzhuo/archive/2010/08/18/eclipse_plugin_1_2_2.html 1. 生成OSGi工程 首先打开新工程 ...

  5. MySQL数据库(一)索引

    索引的作用是操作数据库时避免全表扫描. 索引的机制 B Tree与B+Tree索引 B(blance) 树可以看作是对2-3查找树的一种扩展,即他允许每个节点有M-1个子节点. 根节点至少有两个子节点 ...

  6. tmux:终端复用神器

    一.简介与安装 今天无意间从同事那里知道有 tmux 这种神器,tmux(terminal multiplexer)是Linux上的终端复用神器,可从一个屏幕上管理多个终端(准确说是伪终端).使用该工 ...

  7. ENVOIA

    1,ENVOIA 组织架构讲解 2,开发中的各文件详细讲解 3,系统Data Model讲解 ENOVIA 2012 Online doc文档简介. 介绍ENOVIA组织架构. 介绍ENOVIA前身M ...

  8. 博客美化——Silence主题皮肤

    介绍   一款专注阅读的博客园主题,主要面向于经常混迹 博客园 的朋友.其追求大道至简的终极真理,界面追求简洁.运行追求高效.部署追求简单. 博客皮肤源码地址 预览地址 如何部署.使用皮肤 Silen ...

  9. nginx默认配置文件解释

    nginx默认配置文件 nginx.conf 介绍: 全局配置 user  nginx; 设置nginx服务的系统使用用户 worker_processes  1; 工作进程数(建议和CPU核心数保持 ...

  10. 初学JavaScript正则表达式(十一)

    JavaScript的对象属性 整理自慕课网教学 点此进入