I'm trying to build a variadic function for a constructor in golang and I've ran into an interesting issue. This function is working...
package main
import "fmt"
type person struct {
name string
}
// This is working, but a really Not how I want to do this
func personConstructor(params ...string) person {
name := "Unnamed Person" // Default name
if len(params) > 0 {
name = params[0]
}
return person{name: name}
}
func main() {
bob := personConstructor("Bob")
}
https://play.golang.org/p/dcAdHEQtYz
And yet this, isn't.
package main
import "fmt"
type person struct {
name string
}
// This isn't working
func (p person) constructor(params ...string) person {
name := "Unnamed Person" // Default name
if len(params) > 0 {
name = params[0]
}
return person{name: name}
}
func main() {
bob := person.constructor("Bob")
}
https://play.golang.org/p/YiTQctu-1A
Any idea as to why this is?
Your problem has nothing to do with variadics.
You need to read and learn about method expressions :
https://golang.org/ref/spec#Method_expressions
package main
type person struct {
name string
}
func (p person) constructor(params ...string) person {
name := "Unnamed Person" // Default name
if len(params) > 0 {
name = params[0]
}
return person{name: name}
}
func main() {
// THIS WORKS
person.constructor(person{},"Bob")
}
This compiles but it makes very little sense to do that in your case. the constructor function expect a person receiver. Whether you put it before like
like person{}.constructor("bob") or after like person.constructor(person{},"bob") doesn't matter. constructor expects a person receiver . constructor method is not a "field of some person namespace", this isn't javascript.
If you want to write a constructor function write a factory without a receiver
func NewPerson(params...string)*Person{
// code
}
that's the idiomatic way to do that in Go.
I suggest you to go through the spec once at least.
The introduction in the Go tour provides a concise answer to your question.
Go does not have classes. However, you can define methods on types.
Your examples assume that the constructor function is defined on the definition of the person struct. This is not the case. A method operates on an instance of a type referred to as a receiver. A constructor is not possible in this mechanism. The established pattern within the Go community is to use a factory function to initialize a struct and is exemplified in your first function definition.
The second example provided is failing because constructor is expecting to be called on an instance of a person which is undefined. If you construct a new instance of a person struct the function behaves as expected.
// https://play.golang.org/p/5XDGSTMVj9
func (p person) constructor(params ...string) person {
name := "Unnamed Person" // Default name
if len(params) > 0 {
name = params[0]
}
return person{name: name}
}
func main() {
// Lets define a new instance of a person struct
p := person{}
// The function, when called on a instance, works as expected
bob := p.constructor("Bob")
fmt.Printf("%+v\n", bob)
}
This illustrates that methods are attributed to an instance of a particular type.
Related
In Kotlin, when creating a custom DSL, what is the best way to force filling required fields inside the builder's extension functions in compile time. E.g.:
person {
name = "John Doe" // this field needs to be set always, or compile error
age = 25
}
One way to force it is to set value in a function parameter instead of the body of the extension function.
person(name = "John Doe") {
age = 25
}
but that makes it a bit more unreadable if there are more required fields.
Is there any other way?
New type inference enables you to make a null-safe compile-time checked builder:
data class Person(val name: String, val age: Int?)
// Create a sealed builder class with all the properties that have default values
sealed class PersonBuilder {
var age: Int? = null // `null` can be a default value if the corresponding property of the data class is nullable
// For each property without default value create an interface with this property
interface Named {
var name: String
}
// Create a single private subclass of the sealed class
// Make this subclass implement all the interfaces corresponding to required properties
private class Impl : PersonBuilder(), Named {
override lateinit var name: String // implement required properties with `lateinit` keyword
}
companion object {
// Create a companion object function that returns new instance of the builder
operator fun invoke(): PersonBuilder = Impl()
}
}
// For each required property create an extension setter
fun PersonBuilder.name(name: String) {
contract {
// In the setter contract specify that after setter invocation the builder can be smart-casted to the corresponding interface type
returns() implies (this#name is PersonBuilder.Named)
}
// To set the property, you need to cast the builder to the type of the interface corresponding to the property
// The cast is safe since the only subclass of `sealed class PersonBuilder` implements all such interfaces
(this as PersonBuilder.Named).name = name
}
// Create an extension build function that can only be called on builders that can be smart-casted to all the interfaces corresponding to required properties
// If you forget to put any of these interface into where-clause compiler won't allow you to use corresponding property in the function body
fun <S> S.build(): Person where S : PersonBuilder, S : PersonBuilder.Named = Person(name, age)
Use case:
val builder = PersonBuilder() // creation of the builder via `invoke` operator looks like constructor call
builder.age = 25
// builder.build() // doesn't compile because of the receiver type mismatch (builder can't be smart-casted to `PersonBuilder.Named`)
builder.name("John Doe")
val john = builder.build() // compiles (builder is smart-casted to `PersonBuilder & PersonBuilder.Named`)
Now you can add a DSL function:
// Caller must call build() on the last line of the lambda
fun person(init: PersonBuilder.() -> Person) = PersonBuilder().init()
DSL use case:
person {
name("John Doe") // will not compile without this line
age = 25
build()
}
Finally, on JetBrains open day 2019 it was said that the Kotlin team researched contracts and tried to implement contracts that will allow creating safe DSL with required fields. Here is a talk recording in Russian. This feature isn't even an experimental one, so
maybe it will never be added to the language.
In case you're developing for Android I wrote a lightweight linter to verify mandatory DSL attributes.
To solve your use case you will only need to add an annotation #DSLMandatory to your name property setter and the linter will catch any place when it is not assigned and display an error:
#set:DSLMandatory
var name: String
You can take a look here:
https://github.com/hananrh/dslint/
Simple, throw an exception if it's not defined in your DLS after the block
fun person(block: (Person) -> Unit): Person {
val p = Person()
block(p)
if (p.name == null) {
// throw some exception
}
return p
}
Or if you want to enforce it at build time, just make it return something useless to the outer block if not defined, like null.
fun person(block: (Person) -> Unit): Person? {
val p = Person()
block(p)
if (p.name == null) {
return null
}
return p
}
I'm guessing your going off this example so maybe address would be the better example case:
fun Person.address(block: Address.() -> Unit) {
// city is required
var tempAddress = Address().apply(block)
if (tempAddress.city == null) {
// throw here
}
}
But what if we wanted to ensure everything was defined, but also wanted to let you do it in any order and break at compile time. Simple, have two types!
data class Person(var name: String = null,
var age: Int = null,
var address: Address = null)
data class PersonBuilder(var name: String? = null,
var age: Int? = null,
var address: Address? = null)
fun person(block: (PersonBuilder) -> Unit): Person {
val pb = PersonBuilder()
block(p)
val p = Person(pb.name, pb.age, pb.address)
return p
}
This way, you get to you the non-strict type to build, but it better be null-less by the end. This was a fun question, thanks.
I have highlighted in the test case where I expect something should go. Ideally I would like to test that i is an instance of WHAT_SHOULD_I_PUT_HERE
main.go
package main
import "fmt"
type SomeType struct {
thingThatNeedsSetup struct{}
}
func Create() *SomeType {
return &SomeType{}
}
func main() {
a := Create()
fmt.Println(a.thingThatNeedsSetup)
}
main_test.go
package main
import (
"testing"
)
func TestCreate(t *testing.T) {
i := Create()
if i != WHAT_SHOULD_I_PUT_HERE {
t.Error()
}
}
Go is a typed language and so the go compiler guarantees that a function defined as such
func Create() *SomeType
will always return a value of type *SomeType and because of that your example seems rather pointless.
If on the other hand you define the function as returning an interface, empty or not, e.g.
func Create() interface{}
the underlying type of the returned value could be anything that implements that interface, in which case testing for the underlying type may make sense in some cases.
You can use the reflect package to test whether two values have equal types. Specifically the function reflect.TypeOf which returns a value of type reflect.Type.
From the docs:
Type values are comparable, such as with the == operator. Two Type
values are equal if they represent identical types.
Example:
package main
import (
"testing"
"reflect"
)
func TestCreate(t *testing.T) {
i := Create()
if reflect.TypeOf(i) != reflect.TypeOf(&SomeType{}) {
t.Error()
}
}
rv := reflect.ValueOf(v)
rv.Kind() == reflect.Ptr
I understood that Go has no inheritance and works with composition.
Here is my small example:
type Car struct {
XMLName xml.Name `xml:"response"`
// some properties coming from a XML file
}
type Audi struct {
Car
// some more properties coming from a XML file
}
func UnmarshalFromXML(url string, car *Car) { /* fill the properties from the XML file */ }
What I actually want:
var audi Audi
UnmarshalFromXML("someURL", &audi)
But this does not work, because there is no inheritance. But I need structs to use the unmarshal functionality for XML files.
So what to do?
Inheritance in go very different from another languages. When a type extended from a parent type, the two types remain distinct. The solution in your case is to create an interface, and pass interface as parameter in the function. Take a look to the example below:
package main
import (
"fmt"
)
// creating an interface
type Vehicle interface {
Move()
}
type Car struct {
Color string
Brand string
}
// Car has method Move(), automatically stated implement Vehicle interface
func (c *Car) Move() {
fmt.Print("Car is moving")
}
func(c *Car) Honk() {
fmt.Print("Teeeet... Teet")
}
type Audi struct {
EngineType string
Car
}
// passing an interface
func UnmarshalFromXML(url string, v Vehicle) {
fmt.Print(v)
v.Honk()
}
func main() {
var car = Car{Color:"Green"}
var audi = Audi{}
audi.Car = car
audi.Brand = "Audi"
audi.EngineType = "EC"
UnmarshalFromXML("someURL", &audi)
}
https://play.golang.org/p/ZO4P_3fjmz
This article have a great explanation of OOP in go: http://spf13.com/post/is-go-object-oriented/
You could try using interfaces instead
type Car interface {
theCar()
}
type CarBase struct {
}
func (_ CarBase) theCar() {
}
type Audi struct {
CarBase
}
func UnmarshalFromXML(url string, car Car)
type MainController struct {
beego.Controller
}
func (this *MainController) Post() {
var datapoint User
req := this.Ctx.Input.RequestBody
json.Unmarshal([]byte(req), &datapoint)
this.Ctx.WriteString("hello world")
// result := this.Input()
fmt.Println("input value is", datapoint.UserId)
}
this is normal beego router which executes on url occurrence. I want something like
type MainController struct {
beego.Controller
}
func (this *MainController,db *sql.DB) Post() {
fmt.Println("input value is", datapoint.UserId)
}
in order to use database connection pointer. is this possible to achieve this using go...if not please suggest
You can't do this in golang
type MainController struct {
beego.Controller }
func (this *MainController,db *sql.DB) Post() {
fmt.Println("input value is", datapoint.UserId)
}
the declaration in the form
function (c *MainController)Post()
means that Post is a method for the MainController struct you can pass variable into it.
My suggestion is you declare the db pointer as a global variable in your package like below then you will be able to use it inside the Post function
type MainController struct {
beego.Controller
}
var db *sql.DB
func (this *MainController) Post() {
//you can now use the variable db inside here
fmt.Println("input value is", datapoint.UserId)
}
but considering this is Beego which uses the MVC pattern you can do all this from within the model. I suggest you take a look at their awesome documentation here
How to implement an abstract class in Go? As Go doesn't allow us to have fields in interfaces, that would be a stateless object. So, in other words, is it possible to have some kind of default implementation for a method in Go?
Consider an example:
type Daemon interface {
start(time.Duration)
doWork()
}
func (daemon *Daemon) start(duration time.Duration) {
ticker := time.NewTicker(duration)
// this will call daemon.doWork() periodically
go func() {
for {
<- ticker.C
daemon.doWork()
}
}()
}
type ConcreteDaemonA struct { foo int }
type ConcreteDaemonB struct { bar int }
func (daemon *ConcreteDaemonA) doWork() {
daemon.foo++
fmt.Println("A: ", daemon.foo)
}
func (daemon *ConcreteDaemonB) doWork() {
daemon.bar--
fmt.Println("B: ", daemon.bar)
}
func main() {
dA := new(ConcreteDaemonA)
dB := new(ConcreteDaemonB)
start(dA, 1 * time.Second)
start(dB, 5 * time.Second)
time.Sleep(100 * time.Second)
}
This won't compile as it's not possible to use interface as a receiver.
In fact, I have already answered my question (see the answer below). However, is it an idiomatic way to implement such logic? Are there any reasons not to have a default implementation besides language's simplicity?
The other answers provide an alternative to your problem, however they proposed solution without using abstract classes/struct, and I guess if you were interested in using abstract class like solution, here is very precise solution to your problem:
Go plaground
package main
import (
"fmt"
"time"
)
type Daemon interface {
start(time.Duration)
doWork()
}
type AbstractDaemon struct {
Daemon
}
func (a *AbstractDaemon) start(duration time.Duration) {
ticker := time.NewTicker(duration)
// this will call daemon.doWork() periodically
go func() {
for {
<- ticker.C
a.doWork()
}
}()
}
type ConcreteDaemonA struct {
*AbstractDaemon
foo int
}
func newConcreteDaemonA() *ConcreteDaemonA {
a:=&AbstractDaemon{}
r:=&ConcreteDaemonA{a, 0}
a.Daemon = r
return r
}
type ConcreteDaemonB struct {
*AbstractDaemon
bar int
}
func newConcreteDaemonB() *ConcreteDaemonB {
a:=&AbstractDaemon{}
r:=&ConcreteDaemonB{a, 0}
a.Daemon = r
return r
}
func (a *ConcreteDaemonA) doWork() {
a.foo++
fmt.Println("A: ", a.foo)
}
func (b *ConcreteDaemonB) doWork() {
b.bar--
fmt.Println("B: ", b.bar)
}
func main() {
var dA Daemon = newConcreteDaemonA()
var dB Daemon = newConcreteDaemonB()
dA.start(1 * time.Second)
dB.start(5 * time.Second)
time.Sleep(100 * time.Second)
}
If this is still not obvious how to use abstract classes/multi-inheritance in go-lang here is the post with comprehensive details. Abstract Classes In Go
If you want to provide a "default" implementation (for Daemon.start()), that is not the characteristic of an interface (at least not in Go). That is a characteristic of a concrete (non-interface) type.
So Daemon in your case should be a concrete type, conveniently a struct since you want it to have fields. And the task to be done can be either a value of an interface type, or in a simple case just a function value (a simple case means it would only have one method).
With interface type
Try the complete app on the Go Playground.
type Task interface {
doWork()
}
type Daemon struct {
task Task
}
func (d *Daemon) start(t time.Duration) {
ticker := time.NewTicker(t)
// this will call task.doWork() periodically
go func() {
for {
<-ticker.C
d.task.doWork()
}
}()
}
type MyTask struct{}
func (m MyTask) doWork() {
fmt.Println("Doing my work")
}
func main() {
d := Daemon{task: MyTask{}}
d.start(time.Millisecond*300)
time.Sleep(time.Second * 2)
}
With a function value
In this simple case this one is shorter. Try it on the Go Playground.
type Daemon struct {
task func()
}
func (d *Daemon) start(t time.Duration) {
ticker := time.NewTicker(t)
// this will call task() periodically
go func() {
for {
<-ticker.C
d.task()
}
}()
}
func main() {
d := Daemon{task: func() {
fmt.Println("Doing my work")
}}
d.start(time.Millisecond * 300)
time.Sleep(time.Second * 2)
}
An easy solution is to move daemon *Daemon to the argument list (thus removing start(...) from the interface):
type Daemon interface {
// start(time.Duration)
doWork()
}
func start(daemon Daemon, duration time.Duration) { ... }
func main() {
...
start(dA, 1 * time.Second)
start(dB, 5 * time.Second)
...
}
You can implement abstract class in go.
The definition:
type abstractObject interface{
print()
}
type object struct{
a int
abstractObject
}
Now object is an abstract class, like java's.
You can inherit it and use its members:
type concreteObject struct{
*object
}
(o *concreteObject) print() {
fmt.Println(o.a)
}
func newConcreteObject(o *object) {
obj := &concreteObject{object: o}
o.abstractObject = obj // all magics are in this statement.
}
And use the object with concreteObject's methods:
o := &object{}
newConcereteObject(o)
o.print()
And cast abstract object to concrete object:
concObj := o.abstractObject.(*concreteObject)
Just like other OOP languages.
The solution by Max Malysh would work in some cases if you don't need a factory. However the solution given by Adrian Witas could cause cyclic dependencies issues.
This is the way I achieved implementing an abstract class the easy way respecting cyclic dependencies and good factory patterns.
Let us assume we have the following package structure for our component
component
base
types.go
abstract.go
impl1
impl.go
impl2
impl.go
types.go
factory.go
Define the definition of the component, in this example it will be defined here:
component/types.go
package component
type IComponent interface{
B() int
A() int
Sum() int
Average() int
}
Now let's assume we want to create an abstract class that implements Sum and Average only, but in this abstract implementation we would like to have access to use the values returned by the implemented A and B
To achieve this, we should define another interface for the abstract members of the abstract implementation
component/base/types.go
package base
type IAbstractComponentMembers {
A() int
B() int
}
And then we can proceed to implement the abstract "class"
component/base/abstract.go
package base
type AbstractComponent struct {
IAbstractComponentsMember
}
func (a *AbstractComponent) Sum() int {
return a.A() + a.B()
}
func (a *AbstractComponent) Average() int {
return a.Sum() / 2
}
And now we proceed to the implementations
component/impl1/impl.go // Asume something similar for impl2
package impl1
type ComponentImpl1 struct {
base.AbstractComponent
}
func (c *ComponentImpl1) A() int {
return 2
}
func (c *ComponentImpl1) A() int {
return 4
}
// Here is how we would build this component
func New() *ComponentImpl1 {
impl1 := &ComponentImpl1{}
abs:=&base.AbstractComponent{
IAbstractComponentsMember: impl1,
}
impl1.AbstractComponent = abs
return impl1
}
The reason we use a separate interface for this instead of using Adrian Witas example, is because if we use the same interface in this case, if we import the base package in impl* to use the abstract "class" and also we import the impl* packages in the components package, so the factory can register them, we'll find a circular reference.
So we could have a factory implementation like this
component/factory.go
package component
// Default component implementation to use
const defaultName = "impl1"
var instance *Factory
type Factory struct {
// Map of constructors for the components
ctors map[string]func() IComponent
}
func (f *factory) New() IComponent {
ret, _ := f.Create(defaultName)
return ret
}
func (f *factory) Create(name string) (IComponent, error) {
ctor, ok := f.ctors[name]
if !ok {
return nil, errors.New("component not found")
}
return ctor(), nil
}
func (f *factory) Register(name string, constructor func() IComponent) {
f.ctors[name] = constructor
}
func Factory() *Factory {
if instance == nil {
instance = &factory{ctors: map[string]func() IComponent{}}
}
return instance
}
// Here we register the implementations in the factory
func init() {
Factory().Register("impl1", func() IComponent { return impl1.New() })
Factory().Register("impl2", func() IComponent { return impl2.New() })
}
The functionality of abstract class has below requirements
1. It should not be possible to create direct instance of abstract class
2. It should provide default fields and methods.
A combination of interface and struct can be used to fulfill above two requirements. For example we can see below
package main
import "fmt"
//Abstract Interface
type iAlpha interface {
work()
common(iAlpha)
}
//Abstract Concrete Type
type alpha struct {
name string
}
func (a *alpha) common(i iAlpha) {
fmt.Println("common called")
i.work()
}
//Implementing Type
type beta struct {
alpha
}
func (b *beta) work() {
fmt.Println("work called")
fmt.Printf("Name is %s\n", b.name)
}
func main() {
a := alpha{name: "test"}
b := &beta{alpha: a}
b.common(b)
}
Output:
common called
work called
Name is test
One important point to mention here is that all default method should have iAlpha as first argument, and if default method needs to call any unimplemented method they they will call on this interface. This is same as we did in common method above - i.work().
Source: https://golangbyexample.com/go-abstract-class/