测试嵌套结构中的 nil 值

2024-02-29

我在 go 中有一个深度嵌套的结构。它们是由 json 解组器构造的。

然而,这个结构中的相当多的字段是“omitifempty”,所以我用一个在不同地方可以有空的结构来结束操作。

示例(真实的嵌套更深,而且很大:400 行结构):

package main

import "fmt"

type Foo struct {
    Foo string
    Bar *Bar
}

type Bar struct {
    Bar string
    Baz *Baz
}

type Baz struct {
    Baz string
}

func main() {
    f1 := Foo{Foo: "f1"}
    f2 := Foo{Foo: "f2", Bar: &Bar{Bar: "br2"}}
    f3 := Foo{Foo: "f3", Bar: &Bar{Bar: "br3", Baz: &Baz{Baz: "bz3"}}}

    fmt.Println(f3.Bar.Baz.Baz) //-> bz3
    fmt.Println(f2.Bar.Baz.Baz) //-> panic: runtime error: invalid memory address or nil pointer dereference
    fmt.Println(f1.Bar.Baz.Baz) //-> panic: runtime error: invalid memory address or nil pointer dereference    
    //so far so good, but

    //is there a more generic way to do this kind of testing?
    if f2.Bar != nil && f2.Bar.Baz != nil {
        fmt.Println(f2.Bar.Baz.Baz)
    } else {
        fmt.Println("something nil")
    }
}

问题是是否有一种更通用的方法来测试引用树中的某个节点是否为零?我需要获得很多不同的项目,编写所有这些 if 语句将是一件痛苦的事情。 哦,速度是令人担忧的。


(在我看来)处理它的一种优雅的方法是将 getter 添加到用作指针的结构中。生成的 Go 代码也使用了这种“技术”protobuf https://developers.google.com/protocol-buffers/docs/gotutorial,并且它允许方法调用的自然链接,而不必担心由于nil指针。

在你的例子中Bar and Baz结构体用作指针,因此请为它们配备吸气剂。重点是添加带有指针接收者的方法,首先必须检查接收者是否是nil。如果是,则返回结果类型的零值。如果没有,则继续返回结构体的字段:

func (b *Bar) GetBaz() *Baz {
    if b == nil {
        return nil
    }
    return b.Baz
}

func (b *Baz) GetBaz() string {
    if b == nil {
        return ""
    }
    return b.Baz
}

具有指针接收器的方法的好处是您可以使用以下命令调用它们nil接收器。在您尝试引用它们的字段之前,它不会导致运行时恐慌,而我们不会,这就是为什么我们首先检查接收者是否是nil(最终,接收者充当正常参数 - 并且传递永远不会是错误nil作为指针参数)。

有了上述 getter,使用就简化为这样,并且在这些示例中都不会发生运行时恐慌:

fmt.Println(f3.Bar.GetBaz().GetBaz()) // naturally no panic
fmt.Println(f2.Bar.GetBaz().GetBaz()) // No panic
fmt.Println(f1.Bar.GetBaz().GetBaz()) // No panic

if baz := f2.Bar.GetBaz(); baz != nil {
    fmt.Println(baz.GetBaz())
} else {
    fmt.Println("something nil")
}

尝试一下去游乐场 https://play.golang.org/p/3pDCZYGmDqT.

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

测试嵌套结构中的 nil 值 的相关文章

  • 在 C# 中通过 C DLL 使用数组和指针

    我对 C 非常陌生 上周才开始学习 我有一个用 C 编写的自定义 DLL 具有以下函数 DLLIMPORT void test function double test 我想要做的是从 C 获取数组 test 的指针 因此 如果在 DLL
  • 使用 google.protobuf.Timestamp 在 Go 中解析带有时区偏移的日期时间戳

    我正在创建一个将使用 GRPC 和 protobuf 的 Go 应用程序 我的 RPC 服务应获取包含类型的消息google protobuf Timestamp 解析它并最终将其保存在数据库中或对其执行更多操作 我对什么被认为是该类型的有
  • 无需时间即可生成随机字符串?

    我知道如何使用 Runes 和播种 rand Init 在 go 中生成随机字符串time UnixNano 我的问题是 是否可以 使用 stdlib 在不使用当前时间戳 安全 的情况下播种 rand 此外 我问 因为仅仅依靠时间来为敏感操
  • ReverseProxy取决于golang中的request.Body

    我想构建一个 http 反向代理 它检查 HTTP 主体 然后将 HTTP 请求发送到它的上游服务器 你怎么能在 Go 中做到这一点 初始尝试 如下 失败 因为 ReverseProxy 复制传入请求 修改它并发送 但正文已被读取 func
  • 有没有一种方法可以在不停机的情况下更新 net/http 服务器中的 TLS 证书?

    我有一个简单的 https 服务器 提供一个简单的页面 如下所示 为简洁起见 没有错误处理 package main import crypto tls fmt net http func main mux http NewServeMux
  • 我想在后端验证来自 golang 前端的时区

    前端在注册期间发送时区以及其他用户详细信息 我需要在时区上放置一个验证器来进行 api 测试 时区数据的格式为 GMT 10 00 Hawaii GMT 08 00 Pacific Time US amp Canada 我所做的是定义数组中
  • Go中如何从json字符串中获取键值

    我想尝试从 Go 中的 JSON 获取键值 但我不确定如何操作 我已经能够使用 simplejson 读取 json 值 但是我无法找到如何获取键值 有人能指出我正确的方向和 或帮助我吗 谢谢你 您可以通过执行以下操作来获取 JSON 结构
  • static_cast 和对指针的引用

    谁能告诉我为什么这不能编译 struct A struct B public A int main B b A a b B b1 static cast
  • Go中如何自定义http.Client或http.Transport超时重试?

    我想实现一个自定义http Transport对于标准http Client 如果客户端超时 它将自动重试 附 由于某种原因 习俗http Transport is a 一定有 我已经查过了hashcorp go retryablehttp
  • 在 Go 中跟踪 HTTP 请求时指定超时

    我知道通过执行以下操作来指定 HTTP 请求超时的常用方法 httpClient http Client Timeout time Duration 5 time Second 但是 我似乎不知道在跟踪 HTTP 请求时如何执行相同的操作
  • C 或 C++ 中未初始化的指针有用途吗?

    在其中一篇评论中这个问题 https stackoverflow com questions 1910832 c why arent pointers initialized with null by default 有人指出默认初始化 C
  • 为什么奇数的切片容量与偶数的切片行为不同

    我注意到 当容量为奇数时 切片的容量会以不同的方式表现 更具体地说 当向切片添加元素时 切片的容量为doubled当原始容量为偶数时 但当原容量为奇数时 容量为增加一 然后加倍 例子 s make int 28 28 s append s
  • 如何在 Go 应用程序中处理打开/关闭数据库连接?

    我的 Web API 应用程序中有一组函数 他们对 Postgres 数据库中的数据执行一些操作 func CreateUser db err sql Open postgres user postgres password passwor
  • 我需要一个支持高效随机访问和 O(k) 插入和删除的容器

    我再次尝试问同样的问题question https stackoverflow com questions 3808708 delete parts of a dynamic array and grow other 但我最终提出了一个不同
  • c中的数组名到底是什么?

    我很难理解 C 中数组名称的类型和使用 这可能看起来很长 但请耐心等待 我理解以下声明声明a属于类型int i e 整数数组 int a 30 While a还指向数组的第一个元素以及诸如此类的东西 a 2 是有效的 因此 使得a看起来像一
  • C 中指向常量字符串的指针

    char p string creates pointer to constant string char p string just an array with string 我只是有点困惑为什么它在第一个示例中创建一个指向常量字符串的指
  • Golang 正则表达式命名组和子匹配

    我正在尝试匹配正则表达式并获取匹配的捕获组名称 当正则表达式仅与字符串匹配一次时 这是有效的 但如果它与字符串匹配多次 SubexpNames不返回重复的名称 这是一个例子 package main import fmt regexp fu
  • Golang GAE - 小胡子结构中的 intID

    这是一个Example https www dropbox com sh ur2ws1jnik6euef PjVJSwDTUc Blog Golang zip该应用程序的 关键代码在 golang code handler handler
  • 如何在 Go 中将环境变量传递给测试用例

    在为 Go 编写测试用例时 传递需要提供给测试的环境变量的标准方法是什么 例如 我们不想在测试用例的源代码中嵌入密码 处理这个问题最标准的方法是什么 我们让测试用例寻找配置文件吗 还有别的事吗 看来我偶然发现了答案 将其添加到测试用例中可以
  • 将 char[][] 转换为 char** 会导致段错误吗?

    好吧 我的 C 有点生疏了 但我想我应该用 C 来做我的下一个 小 项目 这样我就可以对其进行抛光 并且我已经有不到 20 行的段错误了 这是我的完整代码 define ROWS 4 define COLS 4 char main map

随机推荐