liujie
liujie
Published on 2025-03-17 / 8 Visits
0
0

GO学习(五)

#Go

go类型转换

数值类型转换

type_name(expression)

var a int = 10
var b float64 = float64(a)

示例:


package main

import "fmt"

func main() {
   var sum int = 17
   var count int = 5
   var mean float32
   
   mean = float32(sum)/float32(count)
   fmt.Printf("mean 的值为: %f\n",mean)
}

字符串类型转换

将字符串变量 str 转换为整型变量 num。

注意,strconv.Atoi 函数返回两个值,第一个是转换后的整型值,第二个是可能发生的错误,我们可以使用空白标识符 _ 来忽略这个错误

var str string = "10"
var num int
num, _ = strconv.Atoi(str)

//将字符串转换为浮点数:
num := 123
str := strconv.Itoa(num)
fmt.Printf("整数 %d  转换为字符串为:'%s'\n", num, str)

接口类型转换

类型断言

类型断言用于将接口类型转换为指定类型,其语法为:

value.(type) 
或者 
value.(T)

其中 value 是接口类型的变量,type 或 T 是要转换成的类型。

如果类型断言成功,它将返回转换后的值和一个布尔值,表示转换是否成功。

package main

import "fmt"

func main() {
    var i interface{} = "Hello, World"
    str, ok := i.(string)
    if ok {
        fmt.Printf("'%s' is a string\n", str)
    } else {
        fmt.Println("conversion failed")
    }
}

类型转换

类型转换用于将一个接口类型的值转换为另一个接口类型,类似与java 的强制类型转换。其语法为:

T(value)

空接口类型

在 Go 语言中,interface{}(空接口)和 Java 的 Object 类似,但它们在类型系统、使用方式和底层实现上有一些重要区别。

  • interface{} 不是一个基类,而是一个接口,它没有任何方法定义,因此任何类型都自动实现了它。

  • Go 的 interface{} 可以直接存储任意类型,包括值类型intfloat64)和引用类型structmap)。

  • 在 Go 语言中,interface{} 变量存储了 两个部分

    1. 动态类型(type):存储该值的实际类型。

    2. 动态值(value):存储该值的实际数据。

var any interface{} = "Hello"
fmt.Printf("Type: %T, Value: %v\n", any, any)

输出:Type: string, Value: Hello

总结

特性

Java Object

Go interface{}

是否可以存储所有类型

只能存储引用类型,基本类型需装箱

可以存储所有类型,包括值类型

是否是基类

是所有类的基类

不是基类,而是接口

是否包含方法

toString()equals()

没有任何方法

运行时类型信息

需要 instanceof 进行类型检查

interface{} 内部包含类型信息

类型转换方式

需要强制类型转换 (String) obj

需要类型断言 v, ok := any.(string)

继承 vs. 接口

依赖继承

依赖接口

性能影响

基本类型需装箱,可能有 GC 开销

存储值类型时有 boxing,类型断言有额外开销

接口

接口的特点

隐式实现
  • Go 中没有关键字显式声明某个类型实现了某个接口。

  • 只要一个类型实现了接口要求的所有方法,该类型就自动被认为实现了该接口。

接口类型变量
  • 接口变量可以存储实现该接口的任意值。

  • 接口变量实际上包含了两个部分:

    • 动态类型:存储实际的值类型。

    • 动态值:存储具体的值。

零值接口
  • 接口的零值是 nil

  • 一个未初始化的接口变量其值为 nil,且不包含任何动态类型或值。

package main

import "fmt"

type Speaker interface {
    Speak()
}

func main() {
    var s Speaker // 此时 s 为 nil
    fmt.Println(s) // 输出 <nil>

    // s.Speak() // 运行时错误:调用 nil 接口的方法
}

空接口
  • 定义为 interface{},可以表示任何类型。

接口的常见用法

  1. 多态:不同类型实现同一接口,实现多态行为。

  2. 泛化:使用空接口 interface{} 表示任意类型。

  3. 解耦:通过接口定义依赖关系,降低模块之间的耦合。允许接口组合

package main

import "fmt"

// 定义接口
type Walker interface {
    Walk()
}

type Talker interface {
    Talk()
}

// 组合接口
type Human interface {
    Walker
    Talker
}

// 结构体实现
type Person struct{}

func (p Person) Walk() {
    fmt.Println("Walking")
}

func (p Person) Talk() {
    fmt.Println("Talking")
}

func main() {
    var h Human = Person{}
    h.Walk()
    h.Talk()
}

对比项

Java 接口

Go 接口

是否需要显式实现

implements 关键字,必须显式实现

隐式实现,只要方法匹配即可

是否可以存储任意类型

Object 只能存储引用类型

interface{} 可存储任意类型

支持多继承吗

只支持多接口继承

允许接口组合

是否可以为 nil

null 不能调用方法,否则 NullPointerException

nil 不能调用方法,否则 panic

设计理念

面向对象(OOP)

面向接口编程(Composition over Inheritance)

错误处理

1. Go 和 Java 错误处理对比

机制

Go

Java

错误表示

error 接口

Exception 类及其子类

错误传播

显式返回 error

抛出异常 throw new Exception()

错误捕获

通过 if err != nil 处理错误

通过 try-catch-finally 处理异常

自定义错误

errors.Newfmt.Errorf

继承 Exception 创建自定义异常

严重错误

panic + recover

RuntimeExceptionError

2. 定义

error 是一个接口类型,定义如下:

任何实现 Error() 方法的类型,都可以作为 error 类型返回。

type error interface {
    Error() string
}

3. 自定义错误

package main

import (
    "errors"
    "fmt"
)

// 定义自定义错误类型
type MyError struct {
    Code int
    Msg  string
}

func (e *MyError) Error() string {
    return fmt.Sprintf("Code: %d, Msg: %s", e.Code, e.Msg)
}

// 可能返回自定义错误
func doSomething(fail bool) error {
    if fail {
        return &MyError{Code: 400, Msg: "Something went wrong"}
    }
    return nil
}

func main() {
    err := doSomething(true)
    if err != nil {
        fmt.Println("Error:", err)
    }
}

4. panic 和 recover

(类似 Java 的 RuntimeException)

Go 不推荐使用 panic,但在 严重错误(如数组越界)时可以使用 panic + recover 处理异常。

g

🔹 解释

  • panic("message") 触发异常。

  • recover() 捕获 panic,防止程序崩溃。

5. errors.Is 和 errors.As

errors.Is

检查某个错误是否是特定错误或由该错误包装而成。

package main

import (
        "errors"
        "fmt"
)

var ErrNotFound = errors.New("not found")

func findItem(id int) error {
        return fmt.Errorf("database error: %w", ErrNotFound)
}

func main() {
        err := findItem(1)
        if errors.Is(err, ErrNotFound) {
                fmt.Println("Item not found")
        } else {
                fmt.Println("Other error:", err)
        }
}

errors.As

将错误转换为特定类型以便进一步处理。


Comment