Search code examples
gooverridingopenapi-generatorgo-modules

Override Function from Another Module in Golang


How do you override a function created in another module in Golang?

Module A

In one module I have the function NewPersonApiService, the full code is laid out as below:

package openapi

import (
    "context"
    "errors"
    "net/http"
)

// PersonApiService is a service that implements the logic for the PersonApiServicer
// This service should implement the business logic for every endpoint for the PersonApi API.
// Include any external packages or services that will be required by this service.
type PersonApiService struct {
}

// NewPersonApiService creates a default api service
func NewPersonApiService() PersonApiServicer {
    return &PersonApiService{}
}

// ShowPerson - Detail
func (s *PersonApiService) ShowPerson(ctx context.Context) (ImplResponse, error) {
    // TODO - update ShowPerson with the required logic for this service method.
    // Add api_person_service.go to the .openapi-generator-ignore to avoid overwriting this service implementation when updating open api generation.

    //TODO: Uncomment the next line to return response Response(200, Person{}) or use other options such as http.Ok ...
    //return Response(200, Person{}), nil

    //TODO: Uncomment the next line to return response Response(0, Error{}) or use other options such as http.Ok ...
    //return Response(0, Error{}), nil

    return Response(http.StatusNotImplemented, nil), errors.New("ShowPerson method not implemented")
}

Module B

In a separate module I want to override this NewPersonApiService.

I can call this function in the other module by doing the following:

package main

import (
    "log"
    "net/http"

    openapi "build/code/spec/src"
)

func main() {

    log.Printf("Server started")

    PersonApiService := openapi.NewPersonApiService()
    PersonApiController := openapi.NewPersonApiController(PersonApiService)

    router := openapi.NewRouter(PersonApiController)

    log.Fatal(http.ListenAndServe(":8080", router))

}

But if I try to override the function I get compilation error, unresolved type for openapi, below is what I was attempting to do:

package main

import (
    "context"
    "log"
    "net/http"

    openapi "build/code/spec/src"
)

func main() {

    log.Printf("Server started")

    PersonApiService := openapi.NewPersonApiService()
    PersonApiController := openapi.NewPersonApiController(PersonApiService)

    router := openapi.NewRouter(PersonApiController)

    log.Fatal(http.ListenAndServe(":8080", router))

}

func (s openapi.PersonApiService) ShowPerson(ctx context.Context) (openapi.ImplResponse, error) {

    return openapi.Response(200, openapi.Person{}), nil
}

Below is an image of the compilation error

enter image description here Additional Info: I believe Module B is properly referencing Module A.

Module A's go.mod file reads as follows:

module build/code/spec

go 1.13

require github.com/go-chi/chi/v5 v5.0.3

Module B's go.mod file reads as follows:

module bakkt.com/boilerplate

go 1.19

replace build/code/spec => ./../build/generated/

require build/code/spec v0.0.0-00010101000000-000000000000

require github.com/go-chi/chi/v5 v5.0.3 // indirect

Solution

  • The solution was to implement the ShowPerson method in another module, you would need to create a new type that implements the PersonApiServicer interface and provides its own implementation of the ShowPerson method.

    Running this in Module B worked and allowed me to change the response of the API call defined in Module A.

    package main
    
    import (
        "context"
        "log"
        "net/http"
    
        openapi "build/code/spec/src"
    )
    
    type MyPersonApiService struct{}
    
    func NewMyPersonApiService() openapi.PersonApiServicer {
        return &MyPersonApiService{}
    }
    
    func (s *MyPersonApiService) ShowPerson(ctx context.Context) (openapi.ImplResponse, error) {
        // TODO: Add your own implementation of the ShowPerson method here.
    
        // For example, you could retrieve a person's details and return them as follows:
        person := openapi.Person{Id: 23, Name: "Vark Thins", Age: 20}
        return openapi.Response(http.StatusOK, person), nil
    }
    
    func main() {
    
        log.Printf("Server started")
    
        PersonApiService := NewMyPersonApiService()
        PersonApiController := openapi.NewPersonApiController(PersonApiService)
    
        router := openapi.NewRouter(PersonApiController)
    
        log.Fatal(http.ListenAndServe(":8080", router))
    
    }