Use private struct members in a template

Is it possible to easily get a copy of all members of a struct, private and public, for read only access? So other packages like template can use them. I don’t like getters and this would require only one.
If I could define a single get to expose the entire struct, a copy of their private values at call time from a package member, that would be great.
As I understand there’s no way to make exported members immutable read only. Getters and setters would be bad.

I would say that you should rethink your requirements. If the author of the type decided to make some if its members private, it probably was for a reason. The decision to not make them public soe they could be used in a template was deliberate.

1 Like

Our company is moving a few projects to Go and we control the packages and the members visibility.
We have very large data models that we need to be able to give read access for all packages but no way to modify them if we don’t add a setter.
How is the Go way to do this? All I could find in SO was that getters and setters shouldn’t be used in Go, and I agree because the boilerplate for us would be enormous. And that I shouldn’t worry about it because it’s easy to refactor if you need to change a field but that’s just non sense, will I have to write tooling to make sure the values are never modified outside the setter?
I feel like I’m missing a feature or design pattern here.

The pattern to make a struct member RO is to not export it and add a funct that returns it.

BTW, I can’t think of any programming language that supports public RO members.

1 Like

No… you can’t easily read unexported struct members from outside the package they were defined.

What you could do is define another struct with the members public and return that instead, eg playground

package main

import (
	"fmt"
)

type DontMessWithMe struct {
	a int
	b string
}

type DontMessWithMeData struct {
	A int
	B string
}

func (d *DontMessWithMe) Data() *DontMessWithMeData {
	return &DontMessWithMeData{
		A: d.a,
		B: d.b,
	}
}

func main() {
	d := DontMessWithMe{a: 1, b: "potato"}
	data := d.Data()
	fmt.Printf("data = %#v\n", data)
}

You could also define the data in a sub structure and return a copy of that, eg (playground)

package main

import (
	"fmt"
)

type DontMessWithMeData struct {
	A int
	B string
}

type DontMessWithMe struct {
	private DontMessWithMeData
}

func (d *DontMessWithMe) Data() *DontMessWithMeData {
	privateCopy := d.private
	return &privateCopy
}

func main() {
	d := DontMessWithMe{private: DontMessWithMeData{A: 1, B: "potato"}}
	data := d.Data()
	fmt.Printf("data = %#v\n", data)
}

this is probably more efficient but changes the datastructure more.

1 Like

I’m aware of at least C# and haxe which have some special syntax to define a field and setter/getter in a special statement. Defining a public key like this makes it actually private and the setter/getter are public. If you define only a getter that way, it’s read only.

And as far as I remember, setter and getter are created in a transparent way, such that setting is done via assignment operator and getting without using parens, just the fieldname.

1 Like

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.