📢 This article was translated by gemini-3-flash-preview
Golang Series
Hello GoLang:
https://blog.yexca.net/archives/154
GoLang (var and const) Variables and Constants:
https://blog.yexca.net/archives/155
GoLang (func) Functions:
https://blog.yexca.net/archives/156
GoLang (slice and map) Slices:
https://blog.yexca.net/archives/160
GoLang (OOP) Object-Oriented Programming: This Article
GoLang (reflect) Reflection:
https://blog.yexca.net/archives/204
GoLang (struct tag) Struct Tags:
https://blog.yexca.net/archives/205
GoLang (goroutine) Goroutines:
https://blog.yexca.net/archives/206
GoLang (channel) Channels:
https://blog.yexca.net/archives/207
Building concepts of classes and objects using structs.
Learn about OOP basics:
OOP Fundamentals
struct
First, custom types. Use the type keyword, similar to C.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
| package main
import "fmt"
type myType int
func main() {
var a myType
fmt.Println("a =", a)
fmt.Printf("type of a is %T", a)
}
/*
* Output
* a = 0
* type of a is main.myType
*/
|
Defining types using struct:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
| package main
import "fmt"
type Person struct {
name string
age int
}
func main() {
var zhang Person
zhang.name = "zhangSan"
zhang.age = 20
fmt.Print(zhang)
}
|
Regarding function parameter passing: it’s pass-by-value if pointers aren’t used.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
| package main
import "fmt"
type Person struct {
name string
age int
}
// Pass by value, won't modify original data
func changeName(person Person) {
person.name = "liSi"
}
// Pass by reference, will modify original data
func changeAge(person *Person) {
person.age = 18
}
func main() {
var zhang Person
zhang.name = "zhangSan"
zhang.age = 20
fmt.Println(zhang)
changeName(zhang)
fmt.Println(zhang)
changeAge(&zhang)
fmt.Println(zhang)
}
|
Encapsulation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
| package main
import "fmt"
// Class
type Person struct {
// Properties
name string
age int
}
// Methods
func (this *Person) SetName(name string) {
this.name = name
}
func (this *Person) SetAge(age int) {
this.age = age
}
func (this *Person) GetName() string {
return this.name
}
func (this *Person) GetAge() int {
return this.age
}
func main() {
person := Person{name: "zhangSan", age: 18}
fmt.Println(person)
}
|
Note that if the first letter of the Class name or Method name is capitalized, it can be accessed by other packages (like public in Java). If the first letter is lowercase, it is package-private (only accessible within the same package). The same applies to property names.
Inheritance
The following code resides in the same file. Parent class:
1
2
3
4
5
6
7
8
9
10
11
12
13
| // Parent class
type Person struct {
name string
age int
}
// Parent methods
func (this *Person) Eat() {
fmt.Println("Person Eat...")
}
func (this *Person) Walk() {
fmt.Println("Person Walk...")
}
|
Child class:
1
2
3
4
5
6
7
8
9
10
11
12
13
| // Child class
type SuperMan struct {
Person // Inherit parent class
level int // Child property
}
// Child overrides parent method
func (this *SuperMan) Walk() {
fmt.Println("SuperMan Walk")
}
// Child specific method
func (this *SuperMan) Fly() {}
|
main function:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
| func main() {
// Define child properties, method 1
superMan1 := SuperMan{Person{"zhangSan", 18}, 4}
// Define child properties, method 2
var superMan2 SuperMan
superMan2.name = "liSi" // Accessible since it's the same package
superMan2.age = 20
superMan2.level = 5
// Child calling parent method
superMan1.Eat()
// Child overridden method
superMan1.Walk()
// Child method
superMan2.Fly()
}
|
Polymorphism
Defining an interface in the same file:
1
2
3
4
5
6
| // Interface, essentially a pointer
type Animal interface {
Sleep()
GetName() string
GetType() string
}
|
Implementation one:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
| // Implementation one
type Cat struct {
name string
kind string
}
// Implement all interface methods
func (this *Cat) Sleep() {
fmt.Println("Cat Sleep()")
}
func (this *Cat) GetName() string {
return this.name
}
func (this *Cat) GetType() string {
return this.kind
}
|
Implementation two:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
| // Implementation two
type Dog struct {
name string
kind string
}
// Implement all interface methods
func (this *Dog) Sleep() {
fmt.Println("Dog Sleep()")
}
func (this *Dog) GetName() string {
return this.name
}
func (this *Dog) GetType() string {
return this.kind
}
func ShowAnimal(animal Animal) {
fmt.Println(animal)
}
|
main:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
| func ShowAnimal(animal Animal) {
fmt.Println(animal)
}
func main() {
var animal Animal
animal = &Cat{"cat1", "cat"}
animal.Sleep()
animal = &Dog{"dog1", "dog"}
animal.Sleep()
cat := Cat{"cat2", "cat"}
dog := Dog{"dog2", "dog"}
ShowAnimal(&cat)
ShowAnimal(&dog)
}
|
Universal Type and Assertions
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
| package main
import "fmt"
// Use empty interface as a universal data type
func f(arg interface{}) {
// Type assertion mechanism (type casting)
value, flag := arg.(string)
if !flag {
fmt.Println("arg is not string type")
} else {
fmt.Println("arg is string type, arg =", value)
}
}
func main() {
// Can pass any data type, including custom ones
f("abc")
f(123)
f(3.14)
}
/*
* Output
* arg is string type, arg = abc
* arg is not string type
* arg is not string type
*/
|