当前位置: 首页 > news >正文

做产品的淘宝客网站招聘网站如何做运营

做产品的淘宝客网站,招聘网站如何做运营,洛阳建设信息网站,给网站做seo的价格1.什么是切片 在 Go 语言中的切片#xff08;slice#xff09;是一种灵活的动态数组#xff0c;它可以自动扩展和收缩#xff0c;是 Go 语言中非常重要的数据结构之一。切片是基于数组实现的#xff0c;它的底层是数组#xff0c;可以理解为对底层数组的抽象。它会生成一…1.什么是切片 在 Go 语言中的切片slice是一种灵活的动态数组它可以自动扩展和收缩是 Go 语言中非常重要的数据结构之一。切片是基于数组实现的它的底层是数组可以理解为对底层数组的抽象。它会生成一个指向数组的指针,并通过切片长度关联到底层数组部分或者全部元素。 2.切片底层结构 在 Go 语言的源码包中src/runtime/slice.go 定义了切片的数据结构 type slice struct {array unsafe.Pointerlen intcap int } 切片占用 24 个字节 array指向底层数组的指针占用 8 个字节。当你创建一个切片时Go 会分配一个底层数组并将切片的指针指向该数组。 len切片中元素的数量占用 8 个字节。 cap切片的容量cap 总是大于等于 len占用 8 个字节。 3.初始化方式 通常用以下三种初始化切片 通过下标的方式获得数组的一部分 slice : arr[1:3] 使用字面量初始化新的切片 slice : []int{1, 2, 3} 使用关键字 make 创建切片 slice : make([]int, 10) //或 slice : make([]int, 3, 5) make函数有三个参数 第一个参数为切片类型可以是[]int[]string[]float32等。第二个参数为切片初始长度。第三个为切片容量该参数为可选参数。 注意点 var slice1 []int 这是声明此时切片为nil 例如 package mainimport fmtfunc main() {var slice1 []intif slice1 nil {fmt.Println(slice is nil!)}// slice1[0] 9 报错panic: runtime error: index out of range [0] with length 0slice1 append(slice1, 2) //可以fmt.Println(slice1) } 结果 slice is nil! [2]4.追加元素 append函数是Go语言内置的一个函数用于向切片中追加元素。 s : []int{1, 2, 3} s append(s, 4) fmt.Println(s) // 输出[1 2 3 4] 或 //如果你要追加的元素是另一个切片那么可以使用...运算符这样可以把那个切片的所有元素都追加进来。 s : []int{1, 2, 3} t : []int{4, 5, 6} s append(s, t...) fmt.Println(s) // 输出[1 2 3 4 5 6] 5.切片表达式 Golang 中通常的 slice 语法是 a[low:high]您可能很熟悉。还有另一种切片语法形式为 a[low:high:max]它采用三个索引而不是两个索引。第三索引 max 是做什么的 提示: 不是 Python 切片语法 a[low:high:step] 中的 step 步长索引。 答: 第三个索引用于设置切片的容量在 Golang 规范中称为 “全切片表达式”。 简单切片表达式的格式[low:high]。 如下面例子n为一个切片当用这个表达式[1:4]表示的是左闭右开[low, high)区间截取一个新的切片例子中结果是[2 3 4]切片被截取之后截取的长度是high-low。 n : []int{1, 2, 3, 4, 5, 6} fmt.Println(n[1:4]) // [2 3 4] 切片表达式的开始low和结束索引high是可选的它们分别默认为零和切片的长度 n : []int{1, 2, 3, 4, 5, 6} fmt.Println(n[:4]) // [1 2 3 4]:前面没有值默认表示0 fmt.Println(n[1:]) // [2 3 4 5 6]:后面没有值默认表示切片的长度 边界问题 1、当n为数组或字符串表达式n[low:high]中low和high的取值关系 0 low high len(n) 2、当n为切片的时候表达式n[low:high]中high最大值变成了cap(n)low和high的取值关系 0 low high cap(n) 不满足以上条件会发送越界panic。 全切片表达式 n[low:high:max] max表示新生成切片的容量新切片容量等于max-low表达式中low、high、max关系 0 low high max cap(n) 继续刚才的例子当计算n[1:4]的容量用cap得到值等于5用扩展表达式n[1:4:5]用cap重新计算得到新的容量值5-1等于4 fmt.Println(cap(n[1:4])) // 5fmt.Println(cap(n[1:4:5])) // 4 关于容量 n[1:4]的长度是3好理解4-1容量为什么是5 因为切片n[1:4]和切片n是共享底层空间所以它的容量并不等于他的长度3根据1等于索引1的位置等于值2从值2这个元素开始到末尾元素6共5个所以n[1:4]容量是5。 如果append超过切片的长度会重新生产一个全新的切片不会覆盖原来的 func main() {n : []int{1, 2, 3, 4, 5, 6}n2 : n[1:4:5] // 长度等于3容量等于4fmt.Printf(%p\n, n2) // 0xc0000220c8n2 append(n2, 5)fmt.Printf(%p\n, n2) // 0xc0000220c8n2 append(n2, 6)fmt.Printf(%p\n, n2) // 地址发生改变0xc00001e080 } 6.常见使用陷阱 切片作为参数传递陷阱 在函数里修改切片元素的值原切片的值也会被改变 在函数里通过 append 方法对切片执行追加元素的操作可能会引起切片扩容导致内存分配的问题可能会对程序的性能 造成影响 在函数里通过 append 函数对切片执行追加元素的操作原切片里不存在新元素。 看一下代码示例 func main() {s : []int{0, 2, 3}fmt.Printf(main中1 切片的长度%d, 切片的容量%d, 切片的元素%v\n, len(s), cap(s), s) // 3 3 [0, 2, 3]sliceOperation(s)fmt.Printf(main中2 切片的长度%d, 切片的容量%d, 切片的元素%v\n, len(s), cap(s), s) // 3 3 [1, 2, 3] }func sliceOperation(s []int) {s[0] 1fmt.Printf(sliceOperation中 切片的长度%d, 切片的容量%d, 切片的元素%v\n, len(s), cap(s), s) // 3 3 [1, 2, 3] } 结果 main中1 切片的长度3, 切片的容量3, 切片的元素[0 2 3] sliceOperation中 切片的长度3, 切片的容量3, 切片的元素[1 2 3] main中2 切片的长度3, 切片的容量3, 切片的元素[1 2 3]看到切片中的元素会被改变就认为改变切片中的元素数据就直接将切片作为参数传过去就可以了但是如果用了append追加元素就会发现追加的元素并不会加到原切片中 func main() {s : []int{0, 2, 3}fmt.Printf(main中1 切片的长度%d, 切片的容量%d, 切片的元素%v\n, len(s), cap(s), s) // 3 3 [0, 2, 3]sliceOperation(s)fmt.Printf(main中2 切片的长度%d, 切片的容量%d, 切片的元素%v\n, len(s), cap(s), s) // 3 3 [1, 2, 3] }func sliceOperation(s []int) {s append(s, 4)fmt.Printf(sliceOperation中 切片的长度%d, 切片的容量%d, 切片的元素%v\n, len(s), cap(s), s) // 4 6 [0, 2, 3] }结果 main中1 切片的长度3, 切片的容量3, 切片的元素[0 2 3] sliceOperation中 切片的长度4, 切片的容量6, 切片的元素[0 2 3 4] main中2 切片的长度3, 切片的容量3, 切片的元素[0 2 3]若想实现执行 append 函数之后原切片也能得到新元素需将函数的参数类型由 切片类型 改成 切片指针类型。 func main() {s : []int{0, 2, 3}fmt.Printf(main中1 切片的长度%d, 切片的容量%d, 切片的元素%v\n, len(s), cap(s), s) sliceOperation(s)fmt.Printf(main中2 切片的长度%d, 切片的容量%d, 切片的元素%v\n, len(s), cap(s), s) }func sliceOperation(s *[]int) {*s append(*s, 4)fmt.Printf(sliceOperation中 切片的长度%d, 切片的容量%d, 切片的元素%v\n, len(*s), cap(*s), s) } 结果 main中1 切片的长度3, 切片的容量3, 切片的元素[0 2 3] sliceOperation中 切片的长度4, 切片的容量6, 切片的元素[0 2 3 4] main中2 切片的长度4, 切片的容量6, 切片的元素[0 2 3 4]slice 通过 make 函数初始化后续操作不当所造成的陷阱 1.使用 make 函数初始化切片后如果在后续操作中没有正确处理切片长度容易造成以下陷阱 func main() {s : make([]int, 0, 4)s[0] 1 // panic: runtime error: index out of range [0] with length 0 } 通过 make([]int, 0, 4) 初始化切片虽说容量为 4但是长度为 0如果通过索引去赋值会发生panic为避免 panic可以通过 s : make([]int, 4) 或 s : make([]int, 4, 4) 对切片进行初始化。 2.切片初始化不当通过 append 函数追加新元素的位置可能于预料之外 func main() {s : make([]int, 4)s append(s, 1)fmt.Println(s[0]) // 0s2 : make([]int, 0, 4)s2 append(s2, 1)fmt.Println(s2[0]) // 1 } 通过打印结果可知对于切片 s元素 1 没有被放置在第一个位置而对于切片 s2元素 1 被放置在切片的第一个位置。这是因为通过 make([]int, 4) 和 make([]int, 0, 4) 初始化切片底层所指向的数组的值是不一样的 第一种初始化的方式切片的长度和容量都为 4底层所指向的数组长度也是 4数组的值为 [0, 0, 0, 0]每个位置的元素被赋值为零值s append(s, 1) 执行后s 切片的值为 [0, 0, 0, 0, 1] 第二种初始化的方式切片的长度为 0容量为 4底层所指向的数组长度为 0数组的值为 []s2 append(s2, 1) 执行后s2 切片的值为 [1] 通过 append 向切片追加元素会执行尾插操作。如果我们需要初始化一个空切片然后从第一个位置开始插入元素需要避免 make([]int, 4) 这种初始化的方式否则添加的结果会在预料之外。 性能陷阱 内存泄露 内存泄露是指程序分配内存后不再使用该内存但未将其释放导致内存资源被浪费。 切片引用切片场景如果一个切片有大量的元素而它只有少部分元素被引用其他元素存在于内存中但是没有被使用则会造成内存泄露。代码示例如下 var s []intfunc main() {sliceOperation()fmt.Println(s)}func sliceOperation() {a : make([]int, 0, 10)a append(a, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10)s a[0:4]} 上述代码中切片 a 的元素有 10 个而切片 s 是基于 a 创建的它底层所指向的数组与 a 所指向的数组是同一个只不过范围为前四个元素而后六个元素依然存在于内存中却没有被使用这样会造成内存泄露。为了避免内存泄露我们可以对代码进行改造s a[0:4] → s append(s, a[0:4]...)通过 append 进行元素追加这样切片 a 底层的数组没有被引用后面会被 gc。 7.切片技巧 Go在Github的官方Wiki上介绍了切片的技巧SliceTricks[4]另外这个项目Go Slice Tricks Cheat Sheet[5]基于SliceTricks做了一系列的图比较直观。 AppendVector 这个是添加一个切片的操作上面我们在切片操作中已经介绍过。 a  append(a, b...)Copy 这边给我们展示了三种copy的写法 b : make([]T, len(a)) copy(b, a)// 效率一般比上面的写法慢但是如果有更多他们效率更好 b  append([]T(nil), a...) b  append(a[:0:0], a...)// 这个实现等价于makecopy。 // 但在Go工具链v1.16上实际上会比较慢。 b  append(make([]T, 0, len(a)), a...)Cut 截掉切片[i,j之间的元素 a  append(a[:i], a[j:]...)CutGC 上面的Cut如果元素是指针的话会存在内存泄露所以我们要对删除的元素设置nil等待GC。 copy(a[i:], a[j:]) for k, n : len(a)-ji, len(a); k  n; k {a[k]  nil // or the zero value of T } a  a[:len(a)-ji]Delete 删除索引位置i的元素 a  append(a[:i], a[i1:]...) // or a  a[:icopy(a[i:], a[i1:])]DeleteGC 删除索引位置i的元素 copy(a[i:], a[i1:]) a[len(a)-1]  nil // or the zero value of T a  a[:len(a)-1]Delete without preserving order 删除索引位置i的元素把最后一位放到索引位置i上然后把最后一位元素删除。这种方式底层并没有发生复制操作。 a[i]  a[len(a)-1]  a  a[:len(a)-1]Delete without preserving orderGC 上面的删除操作元素是一个指针的类型或结构体指针字段会存在最后一个元素不能被GC掉造成泄露把末尾的元素设置nil等待GC。 a[i]  a[len(a)-1] a[len(a)-1]  nil a  a[:len(a)-1]Expand 这个本质上是多个append的组合操作。 a  append(a[:i], append(make([]T, j), a[i:]...)...) Extend 用新列表扩展原来的列表 a  append(a, make([]T, j)...)Filter (in place) 下面代码演示原地删除Go切片元素 n : 0 for _, x : range a {if keep(x) {a[n]  xn} } a  a[:n]Insert a  append(a[:i], append([]T{x}, a[i:]...)...)第二个append会产生新的切片产生一次copy可以用以下代码方式可免去第二次的copy s  append(s, 0 /* 先添加一个0值*/) copy(s[i1:], s[i:]) s[i]  xInsertVector 下面代码演示插入向量封装了动态大小数组的顺序容器的实现 a  append(a[:i], append(b, a[i:]...)...)func Insert(s []int, k int, vs ...int) []int {if n : len(s)  len(vs); n  cap(s) {s2 : s[:n]copy(s2[klen(vs):], s[k:])copy(s2[k:], vs)return s2}s2 : make([]int, len(s)  len(vs))copy(s2, s[:k])copy(s2[k:], vs)copy(s2[klen(vs):], s[k:])return s2 }a  Insert(a, i, b...)Push a  append(a, x)Pop x, a  a[len(a)-1], a[:len(a)-1]Push Front/Unshift a  append([]T{x}, a...)Pop Front/Shift x, a  a[0], a[1:] 7 切片额外技巧 Filtering without allocating 下面例子演示数据过滤的时候b基于原来的a存储空间来操作并没有重新生成新的存储空间。 b : a[:0] for _, x : range a {if f(x) {b  append(b, x)} }为了让截取之后没有使用的存储被GC掉需要设置成nil for i : len(b); i  len(a); i {a[i]  nil // or the zero value of T }Reversing 反转操作演示 for i : len(a)/2-1; i  0; i-- {opp : len(a)-1-ia[i], a[opp]  a[opp], a[i] }还有一种方法 for left, right : 0, len(a)-1; left  right; left, right  left1, right-1 {a[left], a[right]  a[right], a[left] }Shuffling 洗牌算法。算法思想就是从原始数组中随机抽取一个新的数字到新数组中。 for i : len(a) - 1; i  0; i-- {j : rand.Intn(i  1)a[i], a[j]  a[j], a[i] }go1.10之后有内置函数Shuffle[6] Batching with minimal allocation 做批处理大的切片的时候这个技巧可以了解下 actions : []int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9} batchSize : 3 batches : make([][]int, 0, (len(actions)  batchSize - 1) / batchSize)for batchSize  len(actions) {actions, batches  actions[batchSize:], append(batches, actions[0:batchSize:batchSize]) } batches  append(batches, actions)// 结果 // [[0 1 2] [3 4 5] [6 7 8] [9]] In-place deduplicate (comparable) 删除有序数组中的重复项 import sortin : []int{3,2,1,4,3,2,1,4,1} // any item can be sorted sort.Ints(in) j : 0 for i : 1; i  len(in); i {if in[j]  in[i] {continue}j// preserve the original data// in[i], in[j]  in[j], in[i]// only set what is requiredin[j]  in[i] } result : in[:j1] fmt.Println(result) // [1 2 3 4]Move to front, or prepend if not present, in place if possible. 下面代码演示移动指定元素到头部 // moveToFront moves needle to the front of haystack, in place if possible. func moveToFront(needle string, haystack []string) []string {if len(haystack) ! 0  haystack[0]  needle {return haystack}prev : needlefor i, elem : range haystack {switch {case i  0:haystack[0]  needleprev  elemcase elem  needle:haystack[i]  prevreturn haystackdefault:haystack[i]  prevprev  elem}}return append(haystack, prev) }haystack : []string{a, b, c, d, e} // [a b c d e] haystack  moveToFront(c, haystack)         // [c a b d e] haystack  moveToFront(f, haystack)         // [f c a b d e]Sliding Window 下面实现根据size的滑动窗口输出 func slidingWindow(size int, input []int) [][]int {// returns the input slice as the first elementif len(input)  size {return [][]int{input}}// allocate slice at the precise size we needr : make([][]int, 0, len(input)-size1)for i, j : 0, size; j  len(input); i, j  i1, j1 {r  append(r, input[i:j])}return r }func TestSlidingWindow(t *testing.T) {result : slidingWindow(2, []int{1, 2, 3, 4, 5})fmt.Println(result) // [[1 2] [2 3] [3 4] [4 5]] }最后的技巧章节参考微信公众号太白技术 Go切片与技巧附图解
http://www.tj-hxxt.cn/news/131134.html

相关文章:

  • 哪些网站教你做系统网页翻译功能
  • 商城网站建设天软科技网址seo优化排名
  • 有没有专门做老年婚介的网站陕西恒业建设集团网站
  • 做淘宝联盟网站用数据库吗好看的个人网站主页
  • 友情链接是外链吗网站优化排名查询
  • 品牌网是什么网站网站生成app
  • 创建iis网站123邢台招聘信息网
  • 极速网站建设哪家好wordpress如何搬迁
  • 网站建设在哪里发布百度贴吧网页入口
  • 合肥的网站建设剂屏青浦网站设计制作
  • 怎么写网站建设的说明书网络营销实训报告
  • 什么网站可以做设计兼职python完整网站开发项目视频教程
  • 最简单的网站开发软件有哪些株洲网站定制
  • 网站建设兼职工资卖水果网站建设的策划书
  • 网站打开速度进行检测游戏登录器列表更新网站建设
  • wordpress网站页面打开很慢设计师设计网页大概多少钱
  • 网站建设类书籍最好看的网站模板
  • 北京金方网站设计国家信息企业公示系统全国
  • 龙岗区建设规划网站中山营销型网站建设
  • 无锡市太湖新城建设网站网站跳出率高还是低
  • 国家重大建设项目库网站电话简单响应式网站
  • 中文域名网站漯河哪个网站推广效果好
  • 作风建设方面的网站单页网站怎么卖
  • 荣成市住房和城乡建设局网站页面模板怎么添加文章
  • 买完网站怎么建设wordpress cms主题教程
  • 花钱做网站注意些什么宜春做网站的联系电话
  • 华企立方网站四川网站建设的公司排名
  • 网站内容页怎么做的做一般的公司网站需要多少钱
  • 在自己网站建立自己的外链0基础学编程先学什么
  • 河南省住房和城乡建设厅门户网站设计制作小车二教学设计