Как Println может получить доступ к неэкспортированным полям - PullRequest
2 голосов
/ 21 ноября 2019
package test

import (
    "fmt"
)

type DP struct {
    array []int
    cols  int
}

func (v *DP) Init(rs, cs int) {
    v.array = make([]int, rs*cs, rs*cs)
    v.cols = cs
}

func (v *DP) Get(r, c int) int {
    return v.array[r*v.cols+c]
}
package main

import (
    "fmt"
    "test"
)

func main() {
    var k, x, n int
    var dp test.DP
    fmt.Scanf("%d %d %d", &n, &k, &x)
    dp.Init(n, k)
    fmt.Println(dp) // print the contents of dp.array
    fmt.Printf("%d %d %d", n, k, x)
}

Как Println может получить доступ ко всем неэкспортированным полям. Почему он не выдает никакой ошибки, например dp.array undefined (не может ссылаться на неэкспортированный массив или массив методов)

1 Ответ

6 голосов
/ 21 ноября 2019

Поскольку семейство fmt.Print использует reflect, а reflect предоставляет возможность доступа к неэкспортированным полям с reflect.Value.Field. Обратите внимание, что неэкспортированное поле может быть прочитано только таким образом, но не записано.

Некоторый код:

package main

import (
    "fmt"
    "reflect"
)

type A struct {
    A int
    b int
}

func main() {
    fmt.Println("Hello, playground")
    a := A{1, 2}
    va := reflect.ValueOf(&a).Elem()
    exported := va.Field(0)
    unexported, unexportedName := va.Field(1), va.Type().Field(1)
    fmt.Println(unexportedName, unexported)
    // exported settable but unexported not settable
    fmt.Println(exported.CanSet(), unexported.CanSet())
    exported.Set(reflect.ValueOf(int(3)))
    fmt.Println(a)
    // this will panic
    unexported.Set(reflect.ValueOf(int(5)))
    fmt.Println(a)
}

Детская площадка: https://play.golang.org/p/6mhFR7efPEc

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...