Andrei
Andrei

Reputation: 1216

Golang godoc - Explain group type declarations

There is a piece of GO code I have seen in the GIN library and in the Google docs that look like the following

type (
    T0 []string
    T1 []string
    T2 struct{ a, b int }
    T3 struct{ a, c int }
    T4 func(int, float64) *T0
    T5 func(x int, y float64) *[]string
)

What I don't understand is, what this grouping is doing and what are some purposes of this implementation (there wasn't much in the docs that went over this topic unless I missed it)

another example from the gin library

type (
    RoutesInfo []RouteInfo
    RouteInfo  struct {
        Method  string
        Path    string
        Handler string
    }
        Engine struct {
        RouterGroup
        HTMLRender  render.HTMLRender
        allNoRoute  HandlersChain
        allNoMethod HandlersChain
        noRoute     HandlersChain
        noMethod    HandlersChain
        pool        sync.Pool
        trees       methodTrees

        RedirectTrailingSlash bool


        RedirectFixedPath bool      
        HandleMethodNotAllowed bool
        ForwardedByClientIP    bool
    }
)

And lastly - sorry this is different topic but related to this one

var _ IRouter = &Engine{}

why is there a _ infront of IRouter? I know it's a blank identifier but what purpose does it have in that case

Upvotes: 3

Views: 2436

Answers (3)

factotum
factotum

Reputation: 980

Regarding 1st question

The statments shown are type declaration From the Go language spec : A type declaration binds an identifier, the type name, to a new type that has the same underlying type as an existing type, and operations defined for the existing type are also defined for the new type. The new type is different from the existing type.

TypeDecl = "type" ( TypeSpec | "(" { TypeSpec ";" } ")" ) . TypeSpec = identifier Type .

In layman terms, you can do :

type

e.g.

type Temperature uint8
type WeekTemp [7]Temperature

For underlying type, Named instances of the boolean, numeric, and string types are predeclared. Composite types are constructed using type literals

TypeLiteral = ArrayType | StructType | PointerType | FunctionType | InterfaceType | SliceType | MapType | ChannelType .

so you can also equivalently do :

type (
    Temperature unit8
    WeekTemp [7]Temperature
)

another example for composite type

type Tree struct {
    leftChild, rightChild *Tree
}

For 2nd question,

Edited : I wasn't aware of this but trying on go playground , it looks like the answer from jcbwlkr is indeed right.

So trying to compile

type MyInterface interface{
    someMethod() 
}
type MyType struct{}
var _ MyInterface = &MyType{}

will give this error

cannot use MyType literal (type *MyType) as type MyInterface in assignment: *MyType does not implement MyInterface (missing someMethod method)

So it indeed does a compile time check to make sure that Engine struct conforms to IRouter interface. neat

Upvotes: 1

Thundercat
Thundercat

Reputation: 121049

The code

type (
   A int
   B string
)

is functionality identical to

type A int
type B string

The grouping is just a way to organize code. The grouping is sometimes used to indicate that the types are related in some way.

The use of the blank identifier is explained in Specs: What's the purpose of the blank identifier in variable assignment?.

Upvotes: 5

jcbwlkr
jcbwlkr

Reputation: 7999

I think the first part of your question has already been answered. As for the second part, the code

var _ IRouter = &Engine{}

Creates a compile-time check that *Engine implements the IRouter interface. We are assigning a value of type *Engine to a variable that must be of the type IRouter. If a *Engine does not satisfy the interface then it won't compile.

This isn't strictly necessary but some people like to put it in where they define a type to ensure it always satisfies an intended interface.

Upvotes: 4

Related Questions