mbarkhau
mbarkhau

Reputation: 8469

Private type with exported fields

In day 2 of the Go tutorial there is a following exercise.

Why may it be useful to have a private type with exported fields?

For example:

package geometry

type point struct {
    X, Y int;
    name string;
}

Notice that point is lowercase and thus not exported, whereas the fields X and Y are uppercase and thus are. It seems to me, that in order to have access to one of the exported fields, you would have to be able to write something like.

p.X

But in order for that to be possible, p would have to have a declaration like such:

var p geomitry.point;

or

p := new(geomitry.point);

This however is not possible (AFAIK), since the type declaration for point isn't exported.

Upvotes: 15

Views: 7084

Answers (4)

Jesse
Jesse

Reputation: 2908

When using the JSON package (http://golang.org/pkg/json/). You need to have exported fields, to pass a type to json.Marshal(), but you might not want to have that type publicly available to other external packages.

Upvotes: 6

andrers52
andrers52

Reputation: 554

This same question is presented in this Go course as:

[...]You may even have a private type with exported fields. Exercise: when is that useful?

As presented here you can access externally an element defined as internal to a package, you just can't access it directly. In the case of the structure "point" in your example, it means you CANNOT access elements of point directly, as in


// geometry.go

package geometry

type point struct {
    X, Y int
}

// main.go

package main

import (
    "fmt"    
    "./geometry"
)

func main() {
    point := geometry.point{
        X: 10,
        Y: 20
    }

    fmt.Printf("Point: %#v\n", point)
}

But you CAN use the defined point to export elements that use its exported internal elements, as in


// geometry.go

package geometry

type point struct {
    X, Y int
}

//Vector ...
type Vector struct {
    Start point
    End   point
}

// main.go

package main

import (
    "fmt"

    "./geometry"
)

func main() {
    vector := geometry.Vector{}
    vector.Start.X = 10
    vector.Start.Y = 10
    vector.End.X = 10
    vector.End.Y = 10

    fmt.Printf("Vector: %#v\n", vector)
}

Result -> Vector: geometry.Vector{Start:geometry.point{X:10, Y:10}, End:geometry.point{X:10, Y:10}}


So, in my view, this mechanism is meant to give you flexibility in declaring internal data structures.

Upvotes: 3

ppierre
ppierre

Reputation: 188

An abstract base type ?

package geometry

type point struct {
    X, Y int;
}

type Point struct {
    point;
    name string;
}

type Rect struct {
    P1, P2 point;
    name string;
}

Upvotes: 11

Suppressingfire
Suppressingfire

Reputation: 3286

But you could have a public constructor, right?

So if you had a NewGeometryPoint func defined, then you maybe could do (haven't tested against the compiler)

p := NewGeometryPoint(640,480);
fmt.Println("X:",p.X, "Y:",p.Y);

Upvotes: 21

Related Questions