28

is it possible in golang extend struct (something like extend a class in other languages, and use it with functions for old one)

I have https://github.com/xanzy/go-gitlab/blob/master/services.go#L287 type SetSlackServiceOptions

package gitlab

// SetSlackServiceOptions struct
type SetSlackServiceOptions struct {
    WebHook  *string `url:"webhook,omitempty" json:"webhook,omitempty" `
    Username *string `url:"username,omitempty" json:"username,omitempty" `
    Channel  *string `url:"channel,omitempty" json:"channel,omitempty"`
}

And I want to add some fields to the type in my own package. Is It possible to do it, that I can call function SetSlackService with this my own new type?

package gitlab

func (s *ServicesService) SetSlackService(pid interface{}, opt *SetSlackServiceOptions, options ...OptionFunc) (*Response, error) {
    project, err := parseID(pid)
    if err != nil {
        return nil, err
    }
    u := fmt.Sprintf("projects/%s/services/slack", url.QueryEscape(project))

    req, err := s.client.NewRequest("PUT", u, opt, options)
    if err != nil {
        return nil, err
    }

    return s.client.Do(req, nil)
}

https://github.com/xanzy/go-gitlab/blob/266c87ba209d842f6c190920a55db959e5b13971/services.go#L297

Edit:

I want to pass own structure into function above. It's function from gitlab package and I want to extend the http request

JAttanonRadar
  • 463
  • 1
  • 4
  • 11
  • 2
    You can embed existing structs into your own struct types: https://golang.org/ref/spec#Struct_types – abhink Jan 15 '18 at 10:33
  • Please include a [Minimal, Complete, and Verifiable example](https://stackoverflow.com/help/mcve). You should show all (or most) of the information needed in the question itself, not in the form of links. It's also not clear what want to do. You should try embedding the struct in your own type though. – Marc Jan 15 '18 at 10:33
  • 1
    You cannot "extend" a concrete type and then expect your extension to be "passable" to a function that expects the original. – mkopriva Jan 15 '18 at 10:56
  • The answer below seemed answered the edited question. Is there anything wrong? – leaf bebop Jan 15 '18 at 12:09
  • I edited question and add examples of code. – JAttanonRadar Jan 15 '18 at 12:11
  • I can extend struct like this, but I cannot pass it into function in example above, is it even possible in go to do that? – JAttanonRadar Jan 15 '18 at 12:11
  • You can do it using `s.SetSlackService(pid,&YourStruct.SetSlackServiceOptions,...)`. Read [here](https://golang.org/ref/spec#Struct_types) – leaf bebop Jan 15 '18 at 12:17
  • How would you expect this to work with an extended struct, @JAttanonRadar? Say you added a field for, say, using SSL for the connection. How would SetSlackService know about your extended fields? How would it be able to access them without you changing the code in that function itself? – Kaedys Jan 16 '18 at 18:29
  • Can you please uncheck the downvote? I asked 1 question over last year and now i cannot ask another.. I improve my question, so please remove it – JAttanonRadar Feb 07 '18 at 19:26

1 Answers1

32

In go, structures cannot be extended like classes as in other object oriented programming languages. Nor we can add any new field in an existing struct. We can create a new struct embedding the struct that we require to use from different package.

package gitlab

// SetSlackServiceOptions struct
type SetSlackServiceOptions struct {
    WebHook  *string `url:"webhook,omitempty" json:"webhook,omitempty" `
    Username *string `url:"username,omitempty" json:"username,omitempty" `
    Channel  *string `url:"channel,omitempty" json:"channel,omitempty"`
}

In our main package we have to import gitlab package and embed our struct as below:

package main

import "github.com/user/gitlab"

// extend SetSlackServiceOptions struct in another struct
type ExtendedStruct struct {
  gitlab.SetSlackServiceOptions
  MoreValues []string
}

Golang spec define embedded types in struct as:

A field declared with a type but no explicit field name is called an embedded field. An embedded field must be specified as a type name T or as a pointer to a non-interface type name *T, and T itself may not be a pointer type. The unqualified type name acts as the field name.

// A struct with four embedded fields of types T1, *T2, P.T3 and *P.T4
struct {
    T1        // field name is T1
    *T2       // field name is T2
    P.T3      // field name is T3
    *P.T4     // field name is T4
    x, y int  // field names are x and y
}
Himanshu
  • 12,071
  • 7
  • 46
  • 61