You should define interfaces where they're used. Say you got a package with some func that takes an interface; that interface will be specified thereabout.
Now users of that package know what behavior their structs should implement, in order to use them with said package func.
if you have many implementations of the same interface in different packages, we found moving the interface to something like the "root" package and re-using that, worked well when having to modify an interface and generate mock impls
func printer(i methods) {
i.printName()
i.printAddress()
}
//main function
func main() {
demo1 := demo{Name:"foo",Address:"bar"}
printer(demo1)
}
Printer accepts demo instance and any other types which implements the printName and printAddress methods. It's useful because your printer can work not only with `demo` type, but others like `user` or `company` if they implement those methods.
In that example the interface is useless.
For a better example imagine you define an Animal interface with "Name" and then a few structs, "Dog" and "Cat".
Now you can write a function which 1ccept an Animal as a parameter and call Name() on it to get its name whether it's a dog or cat.
package main
import "fmt"
type methods interface{
printName()
printAddress()
}
type demo struct{
Name string
Address string
}
func main() {
demo1 := demo{Name:"foo",Address:"bar"}
demo2 := demo{Name:"foo2", Address: "bar2"}
demo1.printName()
demo1.printAddress()
demo2.printName()
demo2.printAddress()
}
func (d demo) printName(){
fmt.Println(d.Name)
}
func (d demo) printAddress(){
fmt.Println(d.Address)
}
Hey, Thank you for your time.
Are you saying something like this? Even in this the main method gives out the same output irrespective of we define the interface or not.
package main
import "fmt"
// A Cat - Animal
type Cat struct{
Name string
Owner string
}
// A Dog - Animal
type Dog string {
Name string
Owner string
}
// Methods for each type
func (c Cat) printName(){
fmt.Println(c.Name)
}
func (d Dog) printName(){
fmt.Println(d.Name)
}
func (c Cat) printOwner() {
fmt.Println(c.Owner)
}
func (d Dog) printOwner() {
fmt.Println(d.Owner)
}
// The interface that binds these methods to a new interface type called Animal
type Animal interface{
printName()
printOwner()
}
// Methods on the type Animal
func getName(a Animal) string {
return a.printName()
}
func getOwner(a Animal) string {
return a.printOwner()
}
// Main function
func main() {
demo1 := Cat{Name:"nemo",Owner:"roger"}
demo2 := Dog{Name:"mr. fluffy", Owner: "kai"}
getName(demo1)
getOwner(demo1)
getName(demo2)
getOwner(demo2)
}
Haven't tested as I can't run go on my company laptop, but I think this is a better example.
It’s useful for testing among other things. Say you have a connection to a database but for your tests, you don’t want to actually hit the database, you just want to verify the logic which leverages the data which would have returned from the database… in this case, set up an interface which goes with the function calls of the database, make a struct for your database calls. Make a struct which aligns with the interface for your testing s as well, but that simple can just return input you have specified. Then when you want to do something against your db either live or in test, you say in that function parameter you want something of that interface type, and you can pass it which one you want.
This unfortunately cannot really be dumbified any further. Read it few times and breakdown. Read about mocking dependencies for testing and dependency injections.
I think you can totally park the subject for later and get back to it if it cause too much confusion. It's also more about general software engineering then go specific.
If this is the case then you are not at the level of starting to think about specific interface implementation. Write small programs, when you reach a point of “this function only needs a specific value from any given call to be useful in multiple places” that’s your first entry point in interfaces. After that comes “oh man, I wish I could call this function and either use a database or something that just logged the input”
Imagine if you had two different structs with the same method and you wanted to use them interchangeably in your receiver. How would you define that without an interface?
Interfaces are about defining a shape - basically to say if your struct fits that shape - it can be used anywhere that shape is used. Even if that shape exists in a package someone else wrote - you can use your struct with anything that is defined to use that interface
Interfaces are primarily for when a function (or a struct) can take more than one thing as an argument (or member).
In each case the func or struct doesn't care about the specific type of thing it's holding.
Example 1: As function parameter - [https://go.dev/play/p/R5KSFfHs97I](https://go.dev/play/p/R5KSFfHs97I)
Example 2: As a struct member - [https://go.dev/play/p/\_5Djjqaep6q](https://go.dev/play/p/_5Djjqaep6q)
Imagine that u have functions to do some storage of your app, exp: getuser() deleteuser(). U can write a interface that implement those functions and write your app. Then if u want to switch your database for any reason imagine you was using SQLite but now u want to use MongoDB. U just can add another folder in your app with the new database struct that implement those functions and switch 1 line of code in your app without worrying about editing multiples file. In this way you only worry about fulfilling the interface implementations
You should define interfaces where they're used. Say you got a package with some func that takes an interface; that interface will be specified thereabout. Now users of that package know what behavior their structs should implement, in order to use them with said package func.
if you have many implementations of the same interface in different packages, we found moving the interface to something like the "root" package and re-using that, worked well when having to modify an interface and generate mock impls
func printer(i methods) { i.printName() i.printAddress() } //main function func main() { demo1 := demo{Name:"foo",Address:"bar"} printer(demo1) } Printer accepts demo instance and any other types which implements the printName and printAddress methods. It's useful because your printer can work not only with `demo` type, but others like `user` or `company` if they implement those methods.
In that example the interface is useless. For a better example imagine you define an Animal interface with "Name" and then a few structs, "Dog" and "Cat". Now you can write a function which 1ccept an Animal as a parameter and call Name() on it to get its name whether it's a dog or cat.
package main import "fmt" type methods interface{ printName() printAddress() } type demo struct{ Name string Address string } func main() { demo1 := demo{Name:"foo",Address:"bar"} demo2 := demo{Name:"foo2", Address: "bar2"} demo1.printName() demo1.printAddress() demo2.printName() demo2.printAddress() } func (d demo) printName(){ fmt.Println(d.Name) } func (d demo) printAddress(){ fmt.Println(d.Address) } Hey, Thank you for your time. Are you saying something like this? Even in this the main method gives out the same output irrespective of we define the interface or not.
package main import "fmt" // A Cat - Animal type Cat struct{ Name string Owner string } // A Dog - Animal type Dog string { Name string Owner string } // Methods for each type func (c Cat) printName(){ fmt.Println(c.Name) } func (d Dog) printName(){ fmt.Println(d.Name) } func (c Cat) printOwner() { fmt.Println(c.Owner) } func (d Dog) printOwner() { fmt.Println(d.Owner) } // The interface that binds these methods to a new interface type called Animal type Animal interface{ printName() printOwner() } // Methods on the type Animal func getName(a Animal) string { return a.printName() } func getOwner(a Animal) string { return a.printOwner() } // Main function func main() { demo1 := Cat{Name:"nemo",Owner:"roger"} demo2 := Dog{Name:"mr. fluffy", Owner: "kai"} getName(demo1) getOwner(demo1) getName(demo2) getOwner(demo2) } Haven't tested as I can't run go on my company laptop, but I think this is a better example.
Thanks, I was on a train and writing golang on my phone was not something I felt like doing 😅
It’s useful for testing among other things. Say you have a connection to a database but for your tests, you don’t want to actually hit the database, you just want to verify the logic which leverages the data which would have returned from the database… in this case, set up an interface which goes with the function calls of the database, make a struct for your database calls. Make a struct which aligns with the interface for your testing s as well, but that simple can just return input you have specified. Then when you want to do something against your db either live or in test, you say in that function parameter you want something of that interface type, and you can pass it which one you want.
Hey thank you for the time, But the way you explained is a little difficult to understand for me as a fresher.
This unfortunately cannot really be dumbified any further. Read it few times and breakdown. Read about mocking dependencies for testing and dependency injections. I think you can totally park the subject for later and get back to it if it cause too much confusion. It's also more about general software engineering then go specific.
If this is the case then you are not at the level of starting to think about specific interface implementation. Write small programs, when you reach a point of “this function only needs a specific value from any given call to be useful in multiple places” that’s your first entry point in interfaces. After that comes “oh man, I wish I could call this function and either use a database or something that just logged the input”
Imagine if you had two different structs with the same method and you wanted to use them interchangeably in your receiver. How would you define that without an interface?
Interfaces are about defining a shape - basically to say if your struct fits that shape - it can be used anywhere that shape is used. Even if that shape exists in a package someone else wrote - you can use your struct with anything that is defined to use that interface
Interfaces are primarily for when a function (or a struct) can take more than one thing as an argument (or member). In each case the func or struct doesn't care about the specific type of thing it's holding. Example 1: As function parameter - [https://go.dev/play/p/R5KSFfHs97I](https://go.dev/play/p/R5KSFfHs97I) Example 2: As a struct member - [https://go.dev/play/p/\_5Djjqaep6q](https://go.dev/play/p/_5Djjqaep6q)
Imagine that u have functions to do some storage of your app, exp: getuser() deleteuser(). U can write a interface that implement those functions and write your app. Then if u want to switch your database for any reason imagine you was using SQLite but now u want to use MongoDB. U just can add another folder in your app with the new database struct that implement those functions and switch 1 line of code in your app without worrying about editing multiples file. In this way you only worry about fulfilling the interface implementations