Жизнь заставляет вас начать работать с Go
- Самый странный первый момент — это интерфейс.
package main
import (
"fmt"
)
// 定义一个接口
type Shape interface {
Area() float64
}
// 定义一个矩形类型
type Rectangle struct {
Width float64
Height float64
}
// 矩形类型实现Shape接口的Area方法
func (r Rectangle) Area() float64 {
return r.Width * r.Height
}
// 定义一个圆形类型
type Circle struct {
Radius float64
}
// 圆形类型实现Shape接口的Area方法
func (c Circle) Area() float64 {
return 3.14159265359 * c.Radius * c.Radius
}
func main() {
// 创建一个矩形对象
rectangle := Rectangle{
Width: 4, Height: 5}
// 创建一个圆形对象
circle := Circle{
Radius: 3}
// 使用接口来计算不同形状的面积
shapes := []Shape{
rectangle, circle}
for _, shape := range shapes {
fmt.Printf("Area of the shape is: %.2f\n", shape.Area())
}
}
gpt объясняет это: реализация интерфейса в языке Go является неявной, а не явной. Это означает, что вам не нужно явно объявлять, что тип реализует интерфейс.Пока тип предоставляет все методы, определенные в интерфейсе, считается, что он реализует интерфейс. Это гибкая и лаконичная конструкция языка Go.
- Второй странный момент: for in нет, но есть диапазон.Третий
странный момент: как написать массив
func main() {
rec := Rectangle{
width: 2.0, height: 3.0}
cir := Circle{
radius: 2.0}
shapes := []Shape{
rec, cir}
for index, shapes := range shapes {
fmt.Println(index, shapes.Area())
}
}
- Четвертый странный момент: методы зависят от имени метода для определения разрешений: общедоступные или частные.
Методы, начинающиеся с заглавной буквы, являются общедоступными и могут вызываться извне; методы, начинающиеся со строчной буквы, являются частными и не могут быть вызваны извне. ●
Если имя метода начинается с заглавной буквы (например, GetName), метод является общедоступным и доступен вне пакета.
● Если имя метода начинается со строчной буквы (например, «вычислить»), метод является частным и доступен только внутри одного пакета и не может быть доступен за пределами пакета.
package shape
func Description(name string) string {
return "The person name is: " + name
}
func secretName(name string) string {
return "Do not share"
}
4. Странный пятый пункт: обработка ошибок. Я слышал это уже давно.
func main() {
resp, err := http.Get("http://example.com")
if err != nil {
fmt.Println(err)
//return
}
fmt.Println(resp)
num := 5
if inc, err := Increment(num); err != nil {
fmt.Printf("failed number: %v, error message: %v\n", inc, err)
} else {
fmt.Printf("increment successfully, num is %v \n", inc)
}
}
func Increment(n int) (int, error) {
if n < 0 {
return n, errors.New("error")
}
return n + 1, nil
}
- Самое интересное в go: подпрограмму Go можно выполнять одновременно с другой функцией.
func main() {
go task()
fmt.Println("main")
time.Sleep(time.Second * 2)
}
func task() {
fmt.Println("concurrent")
}
канал go: передача данных между двумя процедурами go. Способ написания тоже довольно странный.
package main
import "fmt"
func main(){
c := make(chan string) // 创建channel, 可以发送string类型的数据
go func(){
c <- "hello" }() // 发送端
msg := <-c // 接收端
fmt.Println(msg)
}
Пусть созданная горутина отправит данные:
package main
import (
"fmt"
)
func main() {
ch := make(chan string)
go sc(ch)
fmt.Println(<-ch)
}
// sc函数:只能发送数据给 channel,不能接收数据
func sc(ch chan<- string) {
ch <- "hello"
}
Выбор ожидает несколько каналов: выберите +case, будет выполнен только один
select {
case <-channel1:
// 从channel1接收到数据时执行的代码
case data := <-channel2:
// 从channel2接收到数据时执行的代码
case channel3 <- value:
// 将value发送到channel3时执行的代码
default:
// 如果没有通道操作准备就绪,执行的默认操作
}
package main
import (
"fmt"
"time"
)
func main() {
ch1 := make(chan string)
ch2 := make(chan string)
go func() {
time.Sleep(2 * time.Second)
ch1 <- "Message from channel 1"
}()
go func() {
time.Sleep(1 * time.Second)
ch2 <- "Message from channel 2"
}()
select {
case msg1 := <-ch1:
fmt.Println(msg1)
case msg2 := <-ch2:
fmt.Println(msg2)
}
}