Go语言如何打印含指针的嵌套结构体二维切片(无指针地址)
问题分析
核心问题:
- 虽然给指针类型(
*user、*parent、*oneUsers)实现了String()方法,但打印切片时,默认的格式化输出(如%#v、%v)并不会自动调用切片元素的String()方法,而是直接输出指针的Go语法表示(包含地址)。 - 仅给
*oneUsers实现了String(),但打印的oneUser是oneUsers值类型,不会触发该方法。 user的String()用%#v打印*u时,parent字段作为指针,%#v会直接输出指针地址,而非调用*parent的String()。
解决方案
要实现无指针地址的打印,需要:
- 给值类型切片(
oneUsers、twoUsers)实现String()方法,手动遍历元素并调用其String()来拼接结果。 - 修改
user的String()方法,手动处理parent字段,调用其String()而非依赖%#v。 - 确保所有嵌套层级的打印都由自定义的
String()控制,避免使用默认格式化输出。
修改后的完整代码:
package main import ( "fmt" "strings" ) type parent struct { id int } type user struct { id int name string email string parent *parent } func (u *user) String() string { if u == nil { return "nil" } parentStr := "nil" if u.parent != nil { parentStr = u.parent.String() } return fmt.Sprintf("user{id:%d, name:%q, email:%q, parent:%s}", u.id, u.name, u.email, parentStr) } func (p *parent) String() string { if p == nil { return "nil" } return fmt.Sprintf("parent{id:%d}", p.id) } type oneUsers []*user func (o oneUsers) String() string { if o == nil { return "nil" } var items []string for _, u := range o { items = append(items, u.String()) } return fmt.Sprintf("[%s]", strings.Join(items, ", ")) } type twoUsers []*oneUsers func (t twoUsers) String() string { if t == nil { return "nil" } var items []string for _, o := range t { if o == nil { items = append(items, "nil") } else { items = append(items, o.String()) } } return fmt.Sprintf("[%s]", strings.Join(items, ", ")) } func main() { var oneUser oneUsers p := parent{id: 6} oneUser = append(oneUser, &user{id: 1, name: "cooluser1", email: "cool.user1@gmail.com", parent: &p}) oneUser = append(oneUser, &user{id: 2, name: "cooluser2", email: "cool.user2@gmail.com"}) fmt.Printf("oneUser: %s\n", oneUser) var twoUser twoUsers twoUser = append(twoUser, &oneUser) fmt.Printf("twoUser: %s\n", twoUser) }
输出结果
运行上述代码后,输出将不再包含任何指针地址:
oneUser: [user{id:1, name:"cooluser1", email:"cool.user1@gmail.com", parent:parent{id:6}}, user{id:2, name:"cooluser2", email:"cool.user2@gmail.com", parent:nil}] twoUser: [[user{id:1, name:"cooluser1", email:"cool.user1@gmail.com", parent:parent{id:6}}, user{id:2, name:"cooluser2", email:"cool.user2@gmail.com", parent:nil}]]
关键修改点说明
user.String():不再使用%#v打印整个结构体,手动拼接每个字段,对parent字段直接调用其String()方法,避免指针地址输出。oneUsers.String():给值类型oneUsers实现方法,遍历切片内的*user元素,逐个调用String()后拼接成数组格式的字符串。twoUsers.String():同理,遍历*oneUsers元素,调用其String()方法并拼接,同时处理nil情况。- 打印方式:使用
%s格式化符,直接触发自定义的String()方法,而非默认的%v或%#v。
内容的提问来源于stack exchange,提问作者MengSen
相关产品推荐
相关产品推荐

