How do I ensure a field is defined in struct?

shriek :

This might be a bit silly and I apologize if it is but how do I guarantee that a field is defined in a struct before I can use it?

Let me explain this with example:

package main

import (
    "fmt"
)

type animal struct {
    name     string
    activity func()
}

var elephant = animal{
    name: "elephant",
    activity: func() {
        fmt.Println("Eat grass")
        fmt.Println("Stampede")
    },
}

var lemur = animal{
    name: "lemur",
    activity: func() {
        fmt.Println("Eat fruits")
        fmt.Println("Climb trees")
    },
}

func main() {
    zoo := []animal{
        elephant,
        lemur,
        // more goes here
    }

    for _, cage := range zoo {
        cage.activity()
    }

}

https://play.golang.org/p/0nXNk0DMuVd

Let's say there can be more animal structs in zoo array. Is there a better way to make sure that every animal must define activity function other than doing the following:

for _, cage := range zoo {
    if cage.activity != nil {
      cage.activity()
    }
}

Using method doesn't look feasible here as implementation of activity is quite different for each animal. I was also thinking of using interface but then wouldn't I have to create a type of every animal?
The reason I'm not happy with the above if solution is that the check is done in runtime only. However, if that's the only way to approach this problem then I'm okay with that too.

Muffin Top :

The only way to statically ensure that the function is set for each value is to use methods and an interface. This requires a type for each kind of animal as you noted.

One approach to ensure that function is set a runtime is to use a factory function for creating animal values. This function can check that activity is not nil.

func newAnimal(name string, activity func()) animal {
   if activity == nil {
      panic("missing activity for " + name)
   }
   return animal{name, activity}
}

var elephant = newAnimal("elephant", func() {
    fmt.Println("Eat grass")
    fmt.Println("Stampede")
})

var lemur = newAnimal("lemur", func() {
    fmt.Println("Eat fruits")
    fmt.Println("Climb trees")
})

A variation is to build the zoo using function calls:

type zoo []animal

func addAnimal(name string, activity func()) {
   if activity == nil {
      panic("missing activity for " + name)
   }
   zoo = append(zoo, animal{name, activity})
}

func init() {
  addAnimal("elephant", func() {
    fmt.Println("Eat grass")
    fmt.Println("Stampede")
  })
  addAnimal("lemur", func() {
    fmt.Println("Eat fruits")
    fmt.Println("Climb trees")
  })
}

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related

How do I have a trait field in a struct?

How do I write a struct with an `AlternateScreen` as a field?

How can I add a custom 'weight' field to a Linux process in task_struct and ensure inheritance during forking?

How do I typedef an implementation-defined struct in a generic header?

How do I use sigaction()? struct sigaction is not defined

How can I ensure that a function is "defined" in Python?

How do I move out of a struct field that is an Option?

How do I process enum/struct/field attributes in a procedural macro?

How do I declare a "static" field in a struct in Rust?

How do I set a dynamic struct field in Go?

How do I use reflect to check if the type of a struct field is interface{}?

How do I initialise a const array struct field with the output of a function?

How do I return a reference to the value inside an optional struct field?

How do I access the same field in every struct in my workspace?

How do I update a field in the array of struct in BQ?

How do I get rid of the error "struct field shorthands are unstable"?

How do I match on a struct field in order to mutate it in place?

How do I have a trait as a owned field of a struct?

How do I access a field of nested user defined types?

How do i explain to typescript that a function checked if a field was defined?

How do I use a #defined constant as the max field width in fscanf?

How can I make a struct which may or may not have a field defined?

How do I ensure Google Password Manager stores the correct field as the username?

How do I Marshal a struct with an embdedded struct field to be a flat JSON object in Go?

How do I pass a ref struct argument to a MethodInfo if the struct has a ReadOnlySpan field

How can I ensure an id remains defined after changes to the array?

How do I ensure a number is within a range?

How do I ensure canvas is contained in viewport

Postgresql: How do I ensure that indexes are in memory