为什么无法转换 Slice 类型?

2023-12-08

我想知道为什么你不能这样做:

type Foo struct { A int }
type Bar Foo

foos := []Foo{Foo{1}, Foo{2}}
bars := []Bar(foos)
//cannot convert foos (type []Foo) to type []Bar

我发现这需要运行时对切片执行循环来转换每个元素,这不是 Go 惯用的做法。这是有道理的。

但是,这不能通过编译器仅使用别名来解决吗?Bar as Foo,所以在内部它们是相同的并且它们在下面使用相同的类型标头?我猜答案是否定的,尽管我很好奇为什么。


This:

[]Bar(foos)

是一种类型转换。根据规范,转换有特定的规则:

非常数值x可以转换为类型T在任何这些情况下:

  • x is 可分配的 to T.
  • x的类型和T具有相同的基础类型。
  • x的类型和T是未命名的指针类型,并且它们的指针基类型具有相同的基础类型。
  • x的类型和T都是整数或浮点类型。
  • x的类型和T都是复杂类型。
  • x是一个整数或字节或符文的切片并且T是字符串类型。
  • x是一个字符串并且T是字节或符文的切片。

此处均不适用。为什么?

因为底层类型[]Foo与底层类型不同[]Bar.和类型的值[]Foo不可分配给类型的变量[]Bar, see 可分配性规则在这里.

底层类型为Foo与底层类型相同Bar,但这同样不适用于元素类型为的切片Foo and Bar.

所以以下工作:

type Foo struct{ A int }

type Foos []Foo
type Bars Foos

func main() {
    foos := []Foo{Foo{1}, Foo{2}}
    bars := Bars(foos)

    fmt.Println(bars)
}

输出(尝试一下去游乐场):

[{1} {2}]

请注意,由于实际的内存表示Foo and Bar是相同的(因为底层类型Bar is Foo),在这种情况下使用包unsafe您可以“查看”的值[]Foo作为一个值[]Bar:

type Foo struct{ A int }
type Bar Foo

func main() {
    foos := []Foo{Foo{1}, Foo{2}}

    bars := *(*[]Bar)(unsafe.Pointer(&foos))

    fmt.Println(bars)
    fmt.Printf("%T", bars)
}

This: *(*[]Bar)(unsafe.Pointer(&foos))意味着取地址foos,将其转换为unsafe.Pointer (根据规格所有指针都可以转换为unsafe.Pointer),那么这个Pointer被转换为*[]Bar(再次根据规范Pointer可以转换为任何其他指针类型),然后该指针被取消引用(*运算符),因此结果是类型的值[]Bar如输出中所示。

输出(尝试一下去游乐场):

[{1} {2}]
[]main.Bar

Notes:

引用包文档unsafe:

unsafe 包包含绕过 Go 程序类型安全的操作。

导入不安全的包可能是不可移植的,并且不受 Go 1 兼容性指南的保护。

这是什么意思?这意味着您不应该恢复使用包usafe每次它都会让你的生活变得更轻松。你应该只在特殊情况下使用它,如果不使用它会使你的程序变得非常缓慢和复杂。

在您的程序中,情况并非如此,因为我提出了一个仅进行一点重构的工作示例(Foos and Bars是切片)。

unsafe围绕 Go 类型安全的步骤。这是什么意思?如果你想改变类型foos(例如非常像foos := "trap!"),您的程序仍会编译并运行,但很可能会发生运行时恐慌。使用usafe你会失去编译器的类型检查。

而如果你使用我的其他建议(Foos and Bars),此类更改/拼写错误会在编译时检测到。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

为什么无法转换 Slice 类型? 的相关文章

  • ReverseProxy取决于golang中的request.Body

    我想构建一个 http 反向代理 它检查 HTTP 主体 然后将 HTTP 请求发送到它的上游服务器 你怎么能在 Go 中做到这一点 初始尝试 如下 失败 因为 ReverseProxy 复制传入请求 修改它并发送 但正文已被读取 func
  • Golang标志:忽略丢失的标志并解析多个重复的标志

    我是 Golang 新手 一直无法使用 flag 找到这个问题的解决方案 如何使用 flag 以便我的程序可以处理此类调用 其中 term 标志可能出现可变次数 包括 0 次 myprogram f flag1 myprogram f fl
  • 在 Go 中使用互斥锁

    我想了解互斥体是如何工作的 据我目前的理解 它是为了进行原子操作并同步对某些数据的访问 我在这里构建了一个队列数据结构的示例 https github com arnauddri algorithms blob master data st
  • exec git 命令拒绝重定向到 Go 中的文件

    我试图从 go 调用 git log 并将输出重定向到给定文件 cmdArgs string log numstat reverse fmt Sprintf s HEAD 89c98f5ec48c8ac383ea9e27d792c3dc77
  • 检查值是否实现接口的说明

    我读过 Effective Go 和其他类似这样的问答 golang接口合规性编译类型检查 https stackoverflow com questions 17994519 golang interface compliance com
  • Go中如何自定义http.Client或http.Transport超时重试?

    我想实现一个自定义http Transport对于标准http Client 如果客户端超时 它将自动重试 附 由于某种原因 习俗http Transport is a 一定有 我已经查过了hashcorp go retryablehttp
  • 当涉及多个渠道时,select 如何工作?

    我发现在多个非缓冲通道上使用 select 时 例如 select case lt chana case lt chanb 即使两个通道都有数据 但在处理此选择时 case chana 和 case chanb 的跟注不平衡 package
  • 为什么“valueAsNumber”返回 NaN 作为值?

    在下面的代码中 我试图调用valueAsNumber但我只得到一个 NaN 返回 当我使用parseInt我得到了我期望的结果 为什么是这样
  • 如何将十六进制字符串转换为十进制值

    我尝试将十六进制字符串转换为十进制值 但它没有给我预期的结果 I tried convert toint32 hexa 16 convert todecimal hexa 我有一个看起来像这样的字符串 1 12 94 201 198 我把它
  • GAE Go — 如何对不存在的实体键使用 GetMulti?

    我发现自己需要做一个GetMulti使用键数组进行操作 其中某些实体存在 但有些实体不存在 我当前的代码 如下 返回错误 datastore no such entity err datastore GetMulti c keys info
  • for 循环初始值设定项中的结构

    知道为什么 for 循环初始值设定项中的这个结构表达式在编译时会出现语法错误吗 在这种情况下 指向结构的指针工作正常 但 ofc 我需要如下所示的局部变量 感谢您的建议 type Request struct id int line byt
  • 如何将UTC时间转换为unix时间戳

    我正在寻找将 UTC 时间字符串转换为 unix 时间戳的选项 我的字符串变量是02 28 2016 10 03 46 PM并且需要将其转换为 unix 时间戳 例如1456693426 知道该怎么做吗 首先 unix时间戳14566934
  • 为什么 Go 禁止取 (&) 映射成员的地址,却允许取 (&) 切片元素?

    Go 不允许获取地图成员的地址 if I do this p mm abc Syntax Error cannot take the address of mm abc 理由是 如果 Go 允许使用此地址 那么当地图后台存储增长或缩小时 该
  • 将 2 个字节转换为整数

    我收到一个 2 个字节的端口号 最低有效字节在前 我想将其转换为整数 以便我可以使用它 我做了这个 char buf 2 Where the received bytes are char port 2 port 0 buf 1 port
  • GOMAXPROCS 默认值是多少?

    不设置同名环境变量时是否保证GOMAXPROCS设置为1 此代码显示的值 package main import runtime fmt func getGOMAXPROCS int return runtime GOMAXPROCS 0
  • 有队列实现吗?

    任何人都可以建议使用 Go 容器来实现简单快速的 FIF 队列 Go 有 3 种不同的容器 heap list and vector 哪一种更适合实现队列 事实上 如果您想要的是一个基本且易于使用的 fifo 队列 slice 可以满足您所
  • 正确的文件扩展名或缩写是什么。 golang 的文本/模板?

    我正在考虑为其创建语法荧光笔 但我不知道这种特定类型模板的常规缩写 In 例子之一 http golang org pkg text template example Template helpers从文本 模板 godoc 中 它们引用
  • 为什么 json.Unmarshal 返回映射而不是预期的结构?

    看看这个游乐场 http play golang org p dWku6SPqj5 http play golang org p dWku6SPqj5 基本上 我正在工作的图书馆收到了interface 作为参数 然后需要json Unma
  • Golang 正则表达式在字符串之间替换

    我有一些可能采用以下形式的字符串 MYSTRING MYSTRING n MYSTRING n MYSTRING randomstringwithvariablelength n 我希望能够将其正则表达式为MYSTRING foo 基本上替
  • 直接从一个通道发送到另一个通道

    当从一个通道直接发送到另一个通道时 我偶然发现了令人惊讶的行为 package main import fmt func main my chan make chan string chan of chans make chan chan

随机推荐

  • Nifi:nifi 中的线程

    我想知道线程在 nifi 中如何工作 我的意思是一个处理器有一个线程还是它们在一个主线程中 也许我想从处理器获取一个文件 然后我想更新它 如何防止多个处理器同时获取文件数据 除了使用 keep file false 操作 是否可以在执行脚本
  • JavaScript 排序回调

    我需要对一大堆 Javascript 项目进行排序 我正在使用sort像这样的函数 var sorted list non sorted sort function a b Sort stuff here 我想做的是当sort功能完成 是否
  • 如何使用 UIImagePickerController 录制时使麦克风静音?

    我正在使用 UIImagePickerController 在我的应用程序之一中录制视频 我已成功录制视频 但现在我想在录制视频时将麦克风静音 没有音频的视频 我已经搜索了很多 但没有任何线索 请帮我解决这个问题 是否可能 如果可能的话 比
  • 隔离范围属性何时真正添加到范围中?

    我正在创建一些具有隔离范围和一些别名属性的指令 例如 scope prop1 我的问题是 这些别名到底什么时候添加到范围中 我遇到了一些问题 因为链接函数中未定义属性 运行这个 jsFiddle 后在控制台中查看 http jsfiddle
  • 导入 Math.PI 作为参考或值

    我正在准备 Java 基础认证 我对我正确的问题的答案感到有点困惑 Given public class Circle static double getCircumference double radius return PI 2 rad
  • 释放使用 initWithInteger 创建的 NSNumber 实例:与 numberWithInt:

    书中第326页Objective C 2 0 编程作者说 myNumber NSNumber alloc initWithInt 1000 当然 根据之前的讨论 如果您创建myNumber这样 当您使用完它后 您有责任通过如下语句随后释放它
  • 无法检测类 IllegalArgumentException

    同时从 eclipse 学习和探索 Java 9 我在 eclipse 中创建了一个简单的项目 虽然当我编译该项目时 它打印了程序的预期结果 但也出现了以下异常 Could not instrument class mymodule App
  • 如何在 LINQ 中按大小写排序

    我有这个答案实体框架 OrderBy CASE WHEN 但这只能处理两个选项 var p ctx People OrderBy p gt p IsQualityNetwork 1 p IsEmployee 1 0 1 ThenBy p g
  • 高效的 HTML Div,其中有漏洞

    让我多解释一下 我试图拥有一个大区域 全屏 其中有一个固定大小的孔 该孔将跟随鼠标在屏幕上移动 想象一下 将范围集中在页面上 而页面的其余部分呈灰色 我需要它在所有浏览器 包括 IE 6 中有效地工作 我当前的解决方案使用 4 个 div
  • pthread_create 无法与 pthread_attr_setschedparam 一起正常工作

    我是线程编程的新手 所以我对这个看似愚蠢的问题表示歉意 我正在尝试使用 pthread attr t 使用 pthread create 创建 POSIX 线程 我正在尝试设置 sched priority 值并将其放入属性中 代码粘贴在下
  • 当连接到一个非常小的/空表时,为什么尽管我使用“LIMIT”,MySQL 仍进行完整扫描?

    编辑 我删除了GROUP BY示例查询中的子句 但同样的问题显示 当我将表 x 连接到空 1 行表 y 时 尽管我使用了限制 MySQL 对表 x 进行全表扫描 原问题 我试图学习如何优化 SQL 查询 但遇到了我无法理解的行为 有这样的模
  • 如何从一个表单刷新另一个表单?

    我有两种形式 form1 和 form2 我使用以下代码片段从 form1 调用 form2 Application run new Form2 Form2 f2 new Form2 f2 show 这段代码运行得非常好 我可以看到 for
  • 如何使用 javascript 将数据显示为 HTML

    我在使用 javascript 将数据显示为 HTML 时遇到问题 我创建的代码仅显示最新数据而不是整个数据 我在开发中使用phonegap 这是代码 var oldHtml document getElementById favorite
  • VBA:搜索子字符串并删除整行

    我正在尝试删除字符串中包含 H 的所有行P柱子 然而 该宏有效 每次只删除一半的必要行 这是因为For代码中的循环 当删除一行时 下一行将具有相同的内容i值作为删除的值 并被跳过Next i Dim LastRow As Long Find
  • 在 Windows 10 中设置环境变量以使用 java 和 javac

    我有一台装有 Windows 10 的新笔记本电脑 我想对其进行设置以便可以使用java and javac从命令行 我已经在网上搜索过 但所有指南都是针对以前的版本 我不想搞乱我不明白的东西 只需将环境变量中的path变量设置为JDK b
  • Swift 中的 CLLocation Manager 获取用户位置

    我正在尝试将 ObjC 中的旧应用程序转换为 Swift 作为练习 但遇到了一些问题 我在旧应用程序中的方式是建立 CLLocation Manager 然后我将使用 manager CLLocationManager alloc init
  • 如何在 MATLAB 中测量图像的旋转?

    我有两个图像 一个是原始的 另一个是旋转的 现在 我需要找出图像旋转的角度 到目前为止 我考虑过发现每种颜色的质心 因为我将使用的每个图像都有带有颜色的正方形 并用它来发现图像旋转了多少 但我失败了 我用它来发现图像中较高方块的质心和颜色
  • Webpack 的 stylus-loader 入门

    好吧 新的 我刚刚添加了我的stylus loader style loader 根据推荐stylus loader 和装载机 test styl loader style loader css loader stylus loader 到
  • Hibernate - 它会改变数据库的结构吗?

    我正在 Spring 上用 java 构建更大的项目 很多人建议我使用 hibernate 来简化对数据库的访问 问题是 我必须使用这个项目以前版本的数据库 它曾经是用 PHP 编写的 所以他们肯定没有使用 hibernate 我读过一些有
  • 为什么无法转换 Slice 类型?

    我想知道为什么你不能这样做 type Foo struct A int type Bar Foo foos Foo Foo 1 Foo 2 bars Bar foos cannot convert foos type Foo to type