DEV Community

Discussion on: A story of data hiding and why you shouldn't

Collapse
yujiri8 profile image
Ryan Westlund Author

It's standard library code. It's frozen: golang.org/pkg/net/smtp/

But more generally, I still don't think enforced privacy has the benefit you describe, because the benefit can be had with non-enforced privacy. A non-enforced way of marking a field private (perhaps similar to what Python does) can provide a warning to not use it, but still leave the decision in the hands of the person in a position to know what's best.

Collapse
yoursunny profile image
Junxiao Shi

Go doesn't have warnings.
As I said, you can read unexported fields through reflection.

Thread Thread
yujiri8 profile image
Ryan Westlund Author

Go doesn't have warnings.

I wasn't talking about a language feature called warnings.

I don't even know what process you're talking about with reflection, but why should it have to be any more complicated than just accessing the field?

Thread Thread
yoursunny profile image
Junxiao Shi

Look into the reflect package. It allows you to read unexported fields.

Thread Thread
yujiri8 profile image
Ryan Westlund Author

I found out how to do it for simple types but not for a slice. I needed a field of []string, as its actual type and not as an interface{}.

Thread Thread
yoursunny profile image
Junxiao Shi

play.golang.org/p/u5hi1fE6g3_p

package main

import (
    "fmt"
    "reflect"
)

type X struct {
    y []string
}

func main() {
    x := new(X)
    x.y = []string{"yyyy"}

    vx := reflect.ValueOf(x)
    vy := vx.Elem().FieldByName("y")
    vy0 := vy.Index(0)
    y0 := vy0.String()

    fmt.Println(y0)
}
Enter fullscreen mode Exit fullscreen mode

The Index function does the trick.

Thread Thread
yujiri8 profile image
Ryan Westlund Author

So you're telling me there isn't an actual way to convert directly from a reflect.Value that represents a slice to an actual slice type, I would've had to use Len and Index or Slice to rebuild the slice?

Thread Thread
yoursunny profile image
Junxiao Shi

play.golang.org/p/ADAMCB_GuTE

package main

import (
    "fmt"
    "reflect"
    "unsafe"
)

type X struct {
    y []string
}

func main() {
    x := new(X)
    x.y = []string{"yyyy"}

    vx := reflect.ValueOf(x)
    vy := vx.Elem().FieldByName("y")

    var y []string
    *(*reflect.SliceHeader)(unsafe.Pointer(&y)) = *(*reflect.SliceHeader)(unsafe.Pointer(vy.UnsafeAddr()))

    fmt.Println(y)
}
Enter fullscreen mode Exit fullscreen mode

You can use SliceHeader. However, this requires the unsafe package.

Thread Thread
yujiri8 profile image
Ryan Westlund Author

That is quite some black magic.