【问题标题】:`reflect.Kind()` of Slice Becomes `Struct` When Stored Inside PointerSlice 的`reflect.Kind()` 存储在指针中时变成`Struct`
【发布时间】:2020-03-30 01:17:52
【问题描述】:

检查切片的reflect.Kind() 时,reflect 正确地将其识别为slice,而不是存储在指针中:

package main

import (
    "fmt"
    "reflect"
)

type Dog struct {
    Name string
    Age  int
}

func main() {
    var dogs []Dog
    rDogs := reflect.ValueOf(dogs)
    fmt.Println(rDogs.Kind())
}

输出:

slice

但是,当切片存储在指针中时,reflect.Kind() 将其标识为struct

package main

import (
    "fmt"
    "reflect"
)

type Dog struct {
    Name string
    Age  int
}

func main() {
    dogs1 := make([]Dog, 0)
    pointer := &dogs1
    printPointerValueKind(pointer)        

    var dogs2 []Dog
    pointer = &dogs2
    printPointerValueKind(pointer)
}

func printPointerValueKind(pointer interface{}) {
    if pointer != nil {
        rPointer := reflect.ValueOf(pointer)

        if rPointer.Kind() == reflect.Ptr {
            value := rPointer.Elem()
            rValue := reflect.ValueOf(value)
            fmt.Println(rValue.Kind())
        }
    }
}       

输出:

struct
struct

我的问题是:

  1. 为什么会这样?

  2. 有没有办法将切片存储在指针中,并且仍然让reflect.Kind() 将其识别为slice

【问题讨论】:

  • @mkopriva 我明白了,所以回答 #1。那么#2甚至可能吗?
  • @mkopriva 谢谢!这回答了我的问题!您能否将其添加为答案,以便我接受?
  • 我认为你再次得到了错误问题的正确答案。请参阅godoc.org/github.com/jmoiron/sqlx#Select,它说dest 必须“成为一个切片”:您应该编写var dogs1 []Dog,然后用&dogs1 调用Select,而Select 将填写Dogs1。你做了很多不必要的工作......
  • (顺便说一句,如果我是对的,这是XY problem 的经典示例。)
  • @torek 是的,Select() 适用于切片甚至结构,但我们希望在我们的项目中强制我们将只使用切片,特别是那些已使用 make() 初始化的切片。

标签: pointers go slice reflect


【解决方案1】:

1(reflect.Value).Elem() 返回一个reflect.Value,它一个结构,如果你正在寻找那种不需要再次传递给reflect.ValueOf值所持有的类型。

2rPointer.Elem().Kind() 应该足以满足您的需求。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-03-23
    相关资源
    最近更新 更多