RError.com

RError.com Logo RError.com Logo

RError.com Navigation

  • 主页

Mobile menu

Close
  • 主页
  • 系统&网络
    • 热门问题
    • 最新问题
    • 标签
  • Ubuntu
    • 热门问题
    • 最新问题
    • 标签
  • 帮助
主页 / 问题 / 1567534
Accepted
Space Researcher
Space Researcher
Asked:2024-02-22 16:55:52 +0000 UTC2024-02-22 16:55:52 +0000 UTC 2024-02-22 16:55:52 +0000 UTC

声明段时创建段

  • 772

在我看来,段在声明时并不是被创建的,可能是因为我开始学习《Head First》的那本书。Learning Go » 2020 ISBN 978-5-4461-1395-8(第 210 页)以下是其中的内容: 在此输入图像描述

但我发现一切都是这样的:

package main
import "fmt"

func main() {
    var strArr []string
    fmt.Print(strArr)
    strArr = append(strArr,"qwerty")
    fmt.Print(strArr)
}

结果:

[][qwerty]

...Program finished with exit code 0
Press ENTER to exit console

事实证明,我的信息已经过时,而且这本书是旧版本,或者我弄错了什么。根据我给出的例子,当声明一个段时,它仍然会自动创建,这是真的吗?

golang
  • 2 2 个回答
  • 35 Views

2 个回答

  • Voted
  1. Best Answer
    Pak Uula
    2024-02-22T20:17:25Z2024-02-22T20:17:25Z

    当变量在没有初始化器的情况下声明时,它会被赋值zero value。对于切片来说,这是nil. 您的示例之所以有效,是因为内置函数len,range并且append可以使用 nil 参数正常工作。

    示例: https: //go.dev/play/p/c35hkN_vVbY

    package main
    
    import "fmt"
    
    func IsNilSlice[T any](slice []T) bool { return slice == nil }
    
    func main() {
        var zero []int
        fmt.Println(IsNilSlice(zero))
        empty := []int{}
        fmt.Println(IsNilSlice(empty))
    }
    
    

    结果:

    true
    false
    

    更新

    关于empty := []int{}和var empty []int; empty = make([]int,0)

    该包reflect(目前)包含一个结构体SliceHeader,它实际上是运行时的一个切片:

    type SliceHeader struct {
        Data uintptr
        Len  int
        Cap  int
    }
    

    它由三个字段组成:指向数据的指针、切片的长度以及该字段所指向的内存块的大小Data。

    让我们看看空切片empty := []int{}和是如何var empty []int; empty = make([]int,0):

    package main
    
    import (
        "fmt"
        "reflect"
        "unsafe"
    )
    
    func SliceHeader[T any](slice []T) reflect.SliceHeader {
        hdrp := (*reflect.SliceHeader)(unsafe.Pointer(&slice))
        return *hdrp
    }
    
    func main() {
        s1 := []int{}
        hdr1 := SliceHeader(s1)
        fmt.Printf("[]int{}\t\t: header: %#v\n", hdr1)
        var s2 []int
        s2 = make([]int, 0)
        hdr2 := SliceHeader(s2)
        fmt.Printf("make([]int, 0)\t: header: %#v\n", hdr2)
    }
    

    结果: https: //go.dev/play/p/8puJZ_wTFhJ

    []int{}     : header: reflect.SliceHeader{Data:0xc0000466e8, Len:0, Cap:0}
    make([]int, 0)  : header: reflect.SliceHeader{Data:0xc000084ed0, Len:0, Cap:0}
    

    在这两种情况下,它都是某种指针,零长度和零容量。当然,指向零长度内存位置的指针看起来很奇怪,但对于垃圾收集器来说可能是必要的。

    append分配内存后,指针发生变化:

    func main() {
        s1 := []int{}
        hdr1 := SliceHeader(s1)
        fmt.Printf("[]int{}\t\t\t: header: %#v\n", hdr1)
        var s2 []int
        s2 = make([]int, 0)
        hdr2 := SliceHeader(s2)
        fmt.Printf("make([]int, 0)\t\t: header: %#v\n", hdr2)
    
        s1 = append(s1, 1)
        fmt.Printf("[]int{} appended\t: header: %#v\n", SliceHeader(s1))
    
        s2 = append(s2, 1)
        fmt.Printf("make([]int, 0) appended\t: header: %#v\n", SliceHeader(s2))
    }
    

    结果: https: //go.dev/play/p/yoq-owhbb00

    []int{}         : header: reflect.SliceHeader{Data:0xc000046698, Len:0, Cap:0}
    make([]int, 0)      : header: reflect.SliceHeader{Data:0xc000084e80, Len:0, Cap:0}
    []int{} appended    : header: reflect.SliceHeader{Data:0xc000012078, Len:1, Cap:1}
    make([]int, 0) appended : header: reflect.SliceHeader{Data:0xc000012098, Len:1, Cap:1}
    

    “空”切片的两个版本的行为相同。因此,我们可以假设这些初始化选项是等效的。

    • 3
  2. Vladimir Ignatenko
    2024-02-22T17:21:53Z2024-02-22T17:21:53Z

    我对什么是“段”有点困惑。据我了解,这是切片的翻译。好像通常翻译成“切片”。

    现在进入正题。这是代码

    package main
    
    import "fmt"
    
    func main() {
        var a []string //объявление переменной, пустой слайс
        fmt.Println(a)
        a = make([]string, 7) //выделили память
        fmt.Println(a)
        a = append(a, "qwerty") //добавили строку
        fmt.Println(a)
    }
    

    它给出了这个结果

    []
    [      ]
    [       qwerty]
    
    

    那些。当变量被声明时,它被初始化为空值。如果计划使用这个特定的片段,那么通过make分配内存是有意义的。简单来说, append(不涉及复杂的实现)需要两个切片,确定需要多少内存来放置这两个切片中的数据并分配该内存,然后复制数据。

    那些。在您的示例中,首先声明一个空切片,然后将数据附加到它。总的来说,一切都很正常——事情应该是这样的。您可能误解了书中的信息。

    • 0

相关问题

  • windows上的protoc编译错误

  • 递归打印包依赖

  • Golang 算法 XTEA ECB 库“golang.org/x/crypto/xtea”

  • 如何将 IMEI 转换为字节并返回 golang

  • 如何创建文件并将其移动到新目录?

  • go中的函数参数中是否有cv-qualifier的类似物?

Sidebar

Stats

  • 问题 10021
  • Answers 30001
  • 最佳答案 8000
  • 用户 6900
  • 常问
  • 回答
  • Marko Smith

    我看不懂措辞

    • 1 个回答
  • Marko Smith

    请求的模块“del”不提供名为“default”的导出

    • 3 个回答
  • Marko Smith

    "!+tab" 在 HTML 的 vs 代码中不起作用

    • 5 个回答
  • Marko Smith

    我正在尝试解决“猜词”的问题。Python

    • 2 个回答
  • Marko Smith

    可以使用哪些命令将当前指针移动到指定的提交而不更改工作目录中的文件?

    • 1 个回答
  • Marko Smith

    Python解析野莓

    • 1 个回答
  • Marko Smith

    问题:“警告:检查最新版本的 pip 时出错。”

    • 2 个回答
  • Marko Smith

    帮助编写一个用值填充变量的循环。解决这个问题

    • 2 个回答
  • Marko Smith

    尽管依赖数组为空,但在渲染上调用了 2 次 useEffect

    • 2 个回答
  • Marko Smith

    数据不通过 Telegram.WebApp.sendData 发送

    • 1 个回答
  • Martin Hope
    Alexandr_TT 2020年新年大赛! 2020-12-20 18:20:21 +0000 UTC
  • Martin Hope
    Alexandr_TT 圣诞树动画 2020-12-23 00:38:08 +0000 UTC
  • Martin Hope
    Air 究竟是什么标识了网站访问者? 2020-11-03 15:49:20 +0000 UTC
  • Martin Hope
    Qwertiy 号码显示 9223372036854775807 2020-07-11 18:16:49 +0000 UTC
  • Martin Hope
    user216109 如何为黑客设下陷阱,或充分击退攻击? 2020-05-10 02:22:52 +0000 UTC
  • Martin Hope
    Qwertiy 并变成3个无穷大 2020-11-06 07:15:57 +0000 UTC
  • Martin Hope
    koks_rs 什么是样板代码? 2020-10-27 15:43:19 +0000 UTC
  • Martin Hope
    Sirop4ik 向 git 提交发布的正确方法是什么? 2020-10-05 00:02:00 +0000 UTC
  • Martin Hope
    faoxis 为什么在这么多示例中函数都称为 foo? 2020-08-15 04:42:49 +0000 UTC
  • Martin Hope
    Pavel Mayorov 如何从事件或回调函数中返回值?或者至少等他们完成。 2020-08-11 16:49:28 +0000 UTC

热门标签

javascript python java php c# c++ html android jquery mysql

Explore

  • 主页
  • 问题
    • 热门问题
    • 最新问题
  • 标签
  • 帮助

Footer

RError.com

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

帮助

© 2023 RError.com All Rights Reserve   沪ICP备12040472号-5