Go доступен как с открытым исходным кодом .Хороший способ узнать о рефлексии - посмотреть, как ее используют разработчики ядра Go.Например, пакеты Go fmt и json .Документация по пакету содержит ссылки на файлы исходного кода под заголовком Файлы пакета.
Маршалы и демаршалы пакета JSON Go из структур Go и Go.
Вот пошаговое руководство.-шаговый пример, который устанавливает значение поля struct
, одновременно избегая ошибок.
Пакет Go reflect
имеет функцию CanAddr
.
func (v Value) CanAddr() bool
CanAddr возвращает true, если адрес значения можно получить с помощью Addr.Такие значения называются адресуемыми.Значение является адресуемым, если оно является элементом слайса, элементом адресуемого массива, полем адресуемой структуры или результатом разыменования указателя.Если CanAddr возвращает false, вызов Addr вызовет панику.
Пакет Go reflect
имеет функцию CanSet
, которая, если true
, подразумевает, что CanAddr
также true
.
func (v Value) CanSet() bool
CanSet возвращает true, если значение v можно изменить.Значение может быть изменено, только если оно адресуемое и не было получено с помощью неэкспортированных структурных полей.Если CanSet возвращает false, вызов Set или какой-либо специфический для типа сеттер (например, SetBool, SetInt64) вызовет панику.
Нам нужно убедиться, что мы можем Set
поле struct
.Например,
package main
import (
"fmt"
"reflect"
)
func main() {
type t struct {
N int
}
var n = t{42}
// N at start
fmt.Println(n.N)
// pointer to struct - addressable
ps := reflect.ValueOf(&n)
// struct
s := ps.Elem()
if s.Kind() == reflect.Struct {
// exported field
f := s.FieldByName("N")
if f.IsValid() {
// A Value can be changed only if it is
// addressable and was not obtained by
// the use of unexported struct fields.
if f.CanSet() {
// change value of N
if f.Kind() == reflect.Int {
x := int64(7)
if !f.OverflowInt(x) {
f.SetInt(x)
}
}
}
}
}
// N at end
fmt.Println(n.N)
}
Output:
42
7
Если мы можем быть уверены, что все проверки ошибок не нужны, пример упрощается до
package main
import (
"fmt"
"reflect"
)
func main() {
type t struct {
N int
}
var n = t{42}
fmt.Println(n.N)
reflect.ValueOf(&n).Elem().FieldByName("N").SetInt(7)
fmt.Println(n.N)
}