i am using following code...
package main
import (
"fmt"
)
type traingle interface {
area() int
}
type details struct {
height int
base int
}
func (a details) area() int {
s := a.height + a.base
fmt.Println("the area is", s)
return s
}
func main() {
r := details{height: 3, base: 4}
var p1 traingle
p1.area(r)
}
not getting why getting following error
too many arguments in call to p1.area
have (details)
want ()
i am assuming that p1 object of triangle can call area() method with arguments. not getting why it is failing.
The function area takes no arguments in its definition:
area() int
// ...
func (a details) area() int {
Therefor, passing any arguments to it is, as the error says, too many arguments. There is nowhere in the function where it makes use of arguments. It's making all its calculations based on the properties of its receiver, not any arguments. You're also calling it on an uninitialized (nil) interface value. It looks like what you want is probably:
r := details{height: 3, base: 4}
r.area()
Try this:
package main
import (
"fmt"
)
type shape interface {
area() int
}
type traingle struct {
height int
base int
}
func (a traingle) area() int {
return a.height * a.base / 2
}
func main() {
var p1 shape = traingle{height: 3, base: 4}
fmt.Println(p1.area())
}
output:
6
And see this example on shape: https://stackoverflow.com/a/38818437/8208215
I hope this helps.
Related
package main
import (
"fmt"
)
type shape struct {
name string
}
type square struct {
shape
length int
}
type twoDimensional interface {
area() int
}
func (s square) area() int {
return s.length * s.length
}
func main() {
s1 := square{
length: 2,
}
s1.name = "spongebob"
allSquares := []twoDimensional{
s1,
}
fmt.Println(allSquares[0].name)
}
This is giving me the following error:
./prog.go:36:27: allSquares[0].name undefined (type twoDimensional has no field or method name)
I'm confused about what's going on here. Type square is embedded with type shape, and type square also implements the twoDimensional interface.
If I pass an instance of square into a slice of twoDimensionals, how come I can no longer access type shape from my square?
The interface itself does not have .name attribute. You need to use type assertion allSquares[0].(square) as the following:
package main
import (
"fmt"
)
type shape struct {
name string
}
type square struct {
shape
length int
}
type twoDimensional interface {
area() int
}
func (s square) area() int {
return s.length * s.length
}
func main() {
s1 := square{
length: 2,
}
s1.name = "spongebob"
allSquares := []twoDimensional{
s1,
}
fmt.Println(allSquares[0].(square).name)
}
How come the following code is running? "measure" expects an argument of type geometry, but this code passes argument of "square" type.
package main
import "fmt"
type geometry interface {
area() int
}
type square struct {
radius int
}
func (s square) area() int {
return s.radius*s.radius
}
func measure(g geometry) {
fmt.Println(g)
fmt.Println(g.area())
}
func main() {
measure(square{radius: 3})
}
The outpust is:
{3}
9
Thanks
square implements the geometry interface because it has the method area(). This is exactly the point of interfaces. See: https://tour.golang.org/methods/9
I have two types, B and C, which share all methods, but implement one of them differently. I would like to express this by having a parent type A, containing the implementations of the shared methods, and embedding A in B and C. (Don't Repeat Yourself!) The snag is that the method that differs between B and C is called in many of the shared methods. What's the idiomatic way to structure such code?
My current implementation looks essentially like this (https://play.golang.org/p/RAvH_hBFDN; based on an example by Dave Cheney):
package main
import (
"fmt"
)
type Legger interface {
Legs() int
}
type Cat struct {
Name string
L Legger
}
// Cat has many methods like this, involving calling c.L.Legs()
func (c Cat) PrintLegs() {
fmt.Printf("I have %d legs.\n", c.L.Legs())
}
// OctoCat is a Cat with a particular implementation of Legs
type OctoCat struct {
Cat
}
func (c OctoCat) Legs() int {
return 8
}
// TetraCat has a different implementation of Legs
type TetraCat struct {
Cat
}
func (c TetraCat) Legs() int {
return 4
}
func main() {
c := TetraCat{Cat{"Steve",nil}}
c.L = &c
c.PrintLegs() // want 4
o := OctoCat{Cat{"Bob",nil}}
o.L = &o
o.PrintLegs() // want 8
}
The type definitions themselves look nice and clean, but the initialization code in main is wacky (first the nil in the struct literal, then c.L = &c, what?). Is there a better solution?
A similar pattern was presented in is it possible to call overridden method from parent struct in golang?, but the question of whether this is the idiomatic way to proceed was not answered.
Two approaches I would consider for solving this:
1. Refactor your code to have a single type Cat with the fields Name string and Legs int:
package main
import (
"fmt"
)
type Cat struct {
Name string
Legs int
}
func (c *Cat) PrintLegs() {
fmt.Printf("I have %d legs.\n", c.Legs)
}
func main() {
c := &Cat{"Steve", 4}
c.PrintLegs() // want 4
o := &Cat{"Bob", 8}
o.PrintLegs() // want 8
}
https://play.golang.org/p/_PNAu3sgG8
2. Do away with the Cat type and just have TetraCat and OctoCat implement the Legger interface:
package main
import (
"fmt"
)
type Legger interface {
Legs() int
}
func PrintLegs(l Legger) {
fmt.Printf("I have %d legs.\n", l.Legs())
}
// OctoCat is a Cat with a particular implementation of Legs
type OctoCat struct {
Name string
}
func (c *OctoCat) Legs() int {
return 8
}
// TetraCat has a different implementation of Legs
type TetraCat struct {
Name string
}
func (c *TetraCat) Legs() int {
return 4
}
func main() {
c := &TetraCat{"Steve"}
PrintLegs(c) // want 4
o := &OctoCat{"Bob"}
PrintLegs(o) // want 8
}
https://play.golang.org/p/m4QvKhSj0w
I have problems understanding methods and receivers in Go. Let's say we have this code:
package main
import ("fmt"; "math")
type Circle struct {
x, y, r float64
}
func (c *Circle) area() float64 {
return math.Pi * c.r * c.r
}
func main() {
c := Circle{0, 0, 5}
fmt.Println(c.area())
}
(c *Circle) in the definition of the area function is said to be a receiver and in the main we can call area and pass c by reference without the use of pointers. I can edit the code to the following and it works the same way:
package main
import ("fmt"; "math")
type Circle struct {
x, y, r float64
}
func circleArea(c *Circle) float64 {
return math.Pi * c.r*c.r
}
func main() {
c := Circle{0, 0, 5}
fmt.Println(circleArea(&c))
}
Now is this just a syntactical difference between the two snippets of code or is there something structurally different going on on a deeper level?
The difference isn't just syntax. With a method, your circle type could fulfill an interface, but the function doesn't let you do that:
type areaer interface {
area() float64
}
How to realize "Virtual Inheritance" in Go?
go lang compiler version: "1.3.1 windows/amd64", does it support "Virtual Inheritance" for Go?
I never heard a C like language could support "Virtual", so I really misunderstand.
Virtual Inheritance solves a problem which does not exist if you don't have multiple inheritance. Consider the following inheritance tree:
A
/ \
B C
\ /
D
If classes B and C both provide a data-member (or method for that matter) with the same name then when accessing said member in D, you need a way to disambiguate whose ancestor's data-member (or method) you wish to access.
Virtual Inheritance is C++'s solution.
In Go you don't have inheritance to begin with; only composition and you can embed at most 1 member of any given type at once.
http://play.golang.org/p/1iYzdoFqIC
package main
type B struct {
}
func (b B) Foo() {}
type C struct {
}
func (c C) Foo() {}
type D struct {
B
C
}
func main() {
d := D{B{}, C{}}
// d.Foo() // <- ambiguous
d.B.Foo() // <- ok
d.C.Foo() // <- ok
}
Virtual Inheritance not only solves the problem of multiple inheritance but also gives us polymorphism.
package main
import (
"fmt"
"math"
)
type Form interface {
Color() string
Area() float64
}
type form struct {
color string
}
func (f *form) Color() string {
return f.color
}
type Circle struct {
form
radius float64
}
func (k *Circle) Area() float64 {
return math.Pi * k.radius * k.radius
}
type Rectangle struct {
form
width, height float64
}
func (r *Rectangle) Area() float64 {
return r.width * r.height
}
func main() {
var forms [2]Form
forms[0] = &Circle{
form: form{ "black" },
radius: 5.0,
}
forms[1] = &Rectangle{
form: form{ "read" },
width: 2.0,
height: 3.0,
}
for _, f := range forms {
fmt.Printf("%s: %.2f\n", f.Color(), f.Area())
}
}
Here we have an array of things that have something in common (Color and Area) and we can just iterate over this array calling the same functions and always the right thing will happen.
This is just one advantage of polymorphism. It plays a big role in most design patterns.
"Virtual Inheritance" is something more like this
http://play.golang.org/p/8RvPmB3Pof
package main
type A struct {
virtual int
}
func (a *A) set(v int) {
a.virtual = v
}
func (a *A) get() int {
return a.virtual
}
type B struct {
*A
}
type C struct {
*A
}
type D struct {
*B
*C
}
func main() {
a := &A{}
b := &B{a}
c := &C{a}
d := &D{b, c}
d.B.set(3)
println(d.C.get())
return
}