Go – 访问指针结构体的字段

huangapple go评论111阅读模式
英文:

Go - Accessing fields of a pointer struct

问题

我有一个包含敏感字段(如密码和电子邮件)的User结构体。对于一个公共的User实例,例如活动页面上的公共RSVP,我希望在我的JSON输出中排除敏感字段的显示,即使它们是空的。

根据这篇文章,我正在使用一个复合结构体来屏蔽不需要的字段。

问题:在我的数据库函数中的rows.Scan过程中,我如何正确访问复合结构体中指针结构体的字段?我得到了恐慌错误,因为找不到字段。

我的常规User结构体:

  1. type User struct {
  2. ID int `json:"id"`
  3. FirstName string `json:"firstname"`
  4. LastName string `json:"lastname"`
  5. Registered int `json:"registered"`
  6. Email string `json:"email"`
  7. Password string `json:"password"`
  8. ProfilePic string `json:"profilepic"`
  9. }

根据上述文章中的方法,新增加的结构体:

  1. type omit *struct {}
  2. type PublicUser struct {
  3. *User
  4. Registered omit `json:"registered,omitempty"`
  5. Email omit `json:"email,omitempty"`
  6. Password omit `json:"password,omitempty"`
  7. }

我的数据库函数中出现错误的地方:

  1. func getUsers(db *sql.DB) ([]PublicUser, error) {
  2. query := `SELECT users.id, users.name_first, users.name_last
  3. FROM users
  4. ORDER BY users.name_first asc`
  5. users := []PublicUser{}
  6. rows, err := db.Query(query, e.ID)
  7. if err != nil {
  8. return nil, err
  9. }
  10. defer rows.Close()
  11. for rows.Next() {
  12. var user PublicUser
  13. // 错误发生在这里。似乎在PublicUser中找不到这些字段。
  14. // User的指针是否在我的PublicUser结构体中起作用?
  15. err := rows.Scan(&user.ID, &user.FirstName, &user.LastName)
  16. if err != nil {
  17. return nil, err
  18. }
  19. users = append(users, user)
  20. }
  21. return users, nil
  22. }

我原始的JSON输出,不使用文章中的方法,只使用我的常规User结构体:

  1. [{
  2. "ID": 25,
  3. "FirstName": "Jim",
  4. "LastName": "Brown",
  5. "Registered": 0,
  6. "Email": "",
  7. "Password": "",
  8. "ProfilePic": ""
  9. },
  10. ]

期望的JSON输出:

  1. [{
  2. "ID": 25,
  3. "FirstName": "Jim",
  4. "LastName": "Brown",
  5. "ProfilePic": ""
  6. },
  7. ]

文章链接:https://attilaolah.eu/2014/09/10/json-and-struct-composition-in-go/

英文:

I have a User struct containing sensitive fields like password and email. For a public instance of User, for example a public RSVP on an event page, I want to exclude sensitive fields from appearing in my JSON output, even if they're blank.

Based on this article, I’m using a composite struct to mask undesired fields.

QUESTION: during rows.Scan in my database func, how do I properly access the fields of the pointer struct within the composite struct? I’m getting panic errors thrown, because fields are not being found.

My regular User struct:

  1. type User struct {
  2. ID int `json:"id"`
  3. FirstName string `json:"firstname"`
  4. LastName string `json:"lastname"`
  5. Registered int `json:"registered"`
  6. Email string `json:"email"`
  7. Password string `json:"password"`
  8. ProfilePic string `json:"profilepic"`
  9. }

The new additional structs based on the method in the article linked above:

  1. type omit *struct {
  2. }
  3. type PublicUser struct {
  4. *User
  5. Registered omit `json:”registered,omitempty"`
  6. Email omit `json:”email,omitempty"`
  7. Password omit `json:"password,omitempty"`
  8. }

My database func, where an error is occuring:

  1. func getUsers(db *sql.DB) ([]PublicUser, error) {
  2. query := `SELECT users.id, users.name_first, users.name_last
  3. FROM users
  4. ORDER BY users.name_first asc`
  5. users := []PublicUser{}
  6. rows, err := db.Query(query, e.ID)
  7. if err != nil {
  8. return nil, err
  9. }
  10. defer rows.Close()
  11. for rows.Next() {
  12. var user PublicUser
  13. // ERROR OCCURS HERE. Seems like these fields cannot be found in PublicUser.
  14. // Is the pointer to User working within my PublicUser struct?
  15. err := rows.Scan(&user.ID, &user.FirstName, &user.LastName)
  16. if err != nil {
  17. return nil, err
  18. }
  19. users = append(users, user)
  20. }
  21. return users, nil
  22. }

My original JSON output, not using the articles' method; only using my regular User struct:

  1. [{
  2. "ID": 25,
  3. "FirstName": "Jim",
  4. "LastName": "Brown",
  5. "Registered": 0,
  6. "Email": "",
  7. "Password": "",
  8. "ProfilePic": ""
  9. },
  10. ]

Desired JSON output:

  1. [{
  2. "ID": 25,
  3. "FirstName": "Jim",
  4. "LastName": "Brown",
  5. "ProfilePic": ""
  6. },
  7. ]

答案1

得分: 3

问题在于当你在这里初始化变量时:

  1. var user PublicUser

user 的所有字段都会取它们的“零”值。

由于你嵌入了一个指针,并且指针的零值是 nil,所以你不能在不出错的情况下使用该指针。

为了使其工作,你应该像这样初始化 user

  1. user = PublicUser{ User: &User{} }

(或者不将其声明为指针)

在这里的 playground 中可以看到问题,并且按照上述描述的方式初始化变量使其工作。

https://play.golang.org/p/fXwvATUm_L

英文:

Problem there is that when you initialize the variable here:

  1. var user PublicUser

All the fields for user take their "zero" values.

Since you are embedding a pointer, and zero value for pointers is nil, you can't use that pointer without getting an error.

In order for this to work, you should initialize user like this:

  1. user = PublicUser{ User: &User{} }

(or don't declare it as a pointer)

See a playground here showing the issue and then initializing the variable as described above for it to work.

https://play.golang.org/p/fXwvATUm_L

huangapple
  • 本文由 发表于 2017年9月17日 20:07:52
  • 转载请务必保留本文链接:https://go.coder-hub.com/46263893.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定