2017-05-02 30 views
0

使用Go的反射包,如果指針爲零,是否有方法在結構中設置指針?查看反映包,如果reflect.Value.CanSet()false,則任何Set()調用都會​​產生恐慌。有沒有其他的解決方法,只使用反射包,而不依賴於對結構的任何直接引用?例如,我如何在下面的代碼中將空的姓氏設置爲「Johnson」?Golang在struct中使用反射設置nil字符串指針值

package main 

import (
    "fmt" 
    "reflect" 
) 

type Person struct { 
    FirstName *string 
    LastName *string 
} 

func main() { 
    p := Person{} 
    firstName := "Ryan" 
    p.FirstName = &firstName 

    rp := reflect.ValueOf(p) 
    fmt.Println("rp:", rp) 

    for i := 0; i < rp.NumField(); i++ { 
     fmt.Printf("%s: Pointer: %d CanSet: %t\n", rp.Type().Field(i).Name, rp.Field(i).Pointer(), rp.Field(i).Elem().CanSet()) 
    } 

    rp.Field(0).Elem().SetString("Brian") 
    fmt.Println(*p.FirstName) 

    // Yields nil pointer error 
    // rp.Field(1).Elem().SetString("Johnson") 
    // fmt.Println(*p.LastName) 

    fmt.Println(rp.Field(1).Type()) 
    fmt.Println(rp.Field(1).CanSet()) 
    // fmt.Println(rp.Field(1).Elem().Type()) // nil pointer here also 
    fmt.Println(rp.Field(1).Elem().CanSet()) 
} 

See in Golang Playground

+0

我會在這裏問一個顯而易見的問題。 .. 你爲什麼想做這個?我自己從來沒有見過使用指向字符串指針的很多理由,也沒有看到它們在標準庫中使用。 – RayfenWindspear

+1

公平的問題。當我公開一個REST API時,我知道客戶端是否提供了一個字段。如果它們不是指針,則字符串的空值是''「'。然後,我不得不問,客戶是否提供''「'或者他們沒有提供什麼?另外,我在結構字段中添加了獨特的標籤,如''Validate'和'Transform'。所以,我使用反射包來解析這些。 –

回答

5

你首先需要一個指向Person{},因爲你需要一個值設置爲LastName場。

p := &Person{} 

然後你就可以有效的指針值設置爲LastName領域,這將允許您設置字符串值:

rp.Field(1).Set(reflect.New(rp.Field(1).Type().Elem())) 
rp.Field(1).Elem().SetString("Jones") 

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