【问题标题】:How to print the slice of pointers to get the values instead of their address without iteration at go?如何在不迭代的情况下打印指针切片以获取值而不是它们的地址?
【发布时间】:2019-06-15 13:27:46
【问题描述】:

调试需要这种输出。 为了获得指针切片的实际值,每次都需要迭代。

有什么办法,我们可以使用简单的 fmt.printf() 直接获取值而不是切片中每个项目的地址吗?

这是一个代码 sn-p : https://play.golang.org/p/bQ5vWTlKZmV

package main

import (
    "fmt"
)

type user struct {
    userID int
    name   string
    email  string
}

func main() {
    var users []*user
    addUsers(users)
}

func addUsers(users []*user) {
    users = append(users, &user{userID: 1, name: "cooluser1", email: "cool.user1@gmail.com"})
    users = append(users, &user{userID: 2, name: "cooluser2", email: "cool.user2@gmail.com"})
    printUsers(users)
    printEachUser(users)

}

func printUsers(users []*user) {
    fmt.Printf("users at slice %v \n", users)
}

func printEachUser(users []*user) {
    for index, u := range users {
        fmt.Printf("user at user[%d] is : %v \n", index, *u)
    }
}

在上面的代码中,如果我直接通过 fmt.printf 打印切片,我只得到值的地址而不是实际值本身。

输出:users at slice [0x442260 0x442280]

要始终读取这些值,我必须像 printEachUser 一样调用 func 来迭代切片并获得适当的值。

输出: user at user[0] is : {1 cooluser1 cool.user1@gmail.com} user at user[1] is : {2 cooluser2 cool.user2@gmail.com}

有什么办法,我们可以使用fmt.printf读取指针切片内的值并直接获取值,如下所示?

users at slice [&{1 cooluser1 cool.user1@gmail.com} , &{2 cooluser2 cool.user2@gmail.com}]

【问题讨论】:

  • 不,没有迭代就没有办法。事实上,没有迭代也无法打印值——只是fmt 为您处理了该迭代。但是有一些库会为你做这样的迭代。 spew 可能值得考虑。
  • 哦,是的! fmt 负责迭代。但是,与其依赖其他软件包,您不认为实现fmt.Stringer 会是一个更明智的选择吗? @Flimzy
  • 当然,实现fmt.Stringer 是可行的。哪个是更好的选择取决于您的目标。

标签: go slice


【解决方案1】:

你可以使用spew

go get -u github.com/davecgh/go-spew/spew

func spewDump(users []*user) {
    _, err := spew.Printf("%v", users)
    if err != nil {
        fmt.Println("error while spew print", err)
    }
}

输出:

[<*>{1 cooluser1 cool.user1@gmail.com} <*>{2 cooluser2 cool.user2@gmail.com}]

【讨论】:

【解决方案2】:

调试需要这种输出。

有什么办法,我们可以读取指针切片内的值 使用fmt.Printf 并像下面这样直接获取价值?

users []*user
fmt.Printf("users at slice %v \n", users)

users at slice [&{1 cooluser1 cool.user1@gmail.com}, &{2 cooluser2 cool.user2@gmail.com}]

Package fmt

import "fmt"

type Stringer

Stringer 由任何具有 String 方法的值实现,该方法 定义该值的“本机”格式。使用 String 方法 将作为操作数传递的值打印到任何接受 字符串或打印到未格式化的打印机,例如 Print。

type Stringer interface {
        String() string
}

例如,

package main

import (
    "fmt"
)

type user struct {
    userID int
    name   string
    email  string
}

type users []*user

func (users users) String() string {
    s := "["
    for i, user := range users {
        if i > 0 {
            s += ", "
        }
        s += fmt.Sprintf("%v", user)
    }
    return s + "]"
}

func addUsers(users users) {
    users = append(users, &user{userID: 1, name: "cooluser1", email: "cool.user1@gmail.com"})
    users = append(users, &user{userID: 2, name: "cooluser2", email: "cool.user2@gmail.com"})

    fmt.Printf("users at slice %v \n", users)
}

func main() {
    var users users
    addUsers(users)
}

游乐场:https://play.golang.org/p/vDmdiKQOpqD

输出:

users at slice [&{1 cooluser1 cool.user1@gmail.com}, &{2 cooluser2 cool.user2@gmail.com}] 

【讨论】:

  • 这就是我一直在寻找的,通过实现fmt.Stringer 接口,但对于字符串连接,strings.Builder 会比+ 更好
  • 只定义 (*User).String() 而不是 users.String() 不是更容易吗?
【解决方案3】:

代码:https://play.golang.org/p/rBzVZlovmEc

输出:

用户 [{1 cooluser1 cool.user1@gmail.com} {2 cooluser2 cool.user2@gmail.com}]

使用纵梁可以实现。

参考:https://golang.org/pkg/fmt/#Stringer

package main

import (
    "fmt"
)

type user struct {
    userID int
    name   string
    email  string
}

func (t user) String() string {
    return fmt.Sprintf("{%v %v %v}", t.userID, t.name, t.email)
}

func main() {
    var users []*user
    addUsers(users)
}

func addUsers(users []*user) {
    users = append(users, &user{userID: 1, name: "cooluser1", email: "cool.user1@gmail.com"})
    users = append(users, &user{userID: 2, name: "cooluser2", email: "cool.user2@gmail.com"})
    printUsers(users)
}

func printUsers(users []*user) {
    fmt.Printf("users at slice %v \n", users)
}

您不需要将字符串应用于用户,即 []*users,如果您只为单个用户执行此操作,它会正常工作。它还减少了您需要手动执行的字符串操作,使您的代码更优雅。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-06-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-22
    • 1970-01-01
    • 2021-12-10
    • 1970-01-01
    相关资源
    最近更新 更多