面试题答案
一键面试以下是一个使用 Go 语言解决该问题的示例代码:
package main
import (
"fmt"
"reflect"
"sync"
)
// 获取结构体字段值并存储在 interface{} 切片中
func getFieldsAsInterfaces(s interface{}) ([]interface{}, error) {
value := reflect.ValueOf(s)
if value.Kind() == reflect.Ptr {
value = value.Elem()
}
if value.Kind() != reflect.Struct {
return nil, fmt.Errorf("input is not a struct")
}
var result []interface{}
for i := 0; i < value.NumField(); i++ {
result = append(result, value.Field(i).Interface())
}
return result, nil
}
// 从 interface{} 切片还原值并处理类型断言错误
func restoreValues(interfaceSlice []interface{}, wg *sync.WaitGroup) {
defer wg.Done()
for _, v := range interfaceSlice {
switch v := v.(type) {
case string:
fmt.Printf("String value: %s\n", v)
case int:
fmt.Printf("Int value: %d\n", v)
case float64:
fmt.Printf("Float64 value: %f\n", v)
default:
fmt.Printf("Unsupported type: %T\n", v)
}
}
}
func main() {
type MyStruct struct {
Name string
Age int
Score float64
}
myStruct := MyStruct{
Name: "John",
Age: 30,
Score: 85.5,
}
interfaceSlice, err := getFieldsAsInterfaces(myStruct)
if err != nil {
fmt.Println(err)
return
}
var wg sync.WaitGroup
wg.Add(1)
go restoreValues(interfaceSlice, &wg)
wg.Wait()
}
代码说明
getFieldsAsInterfaces
函数:- 使用
reflect.ValueOf
获取传入结构体的Value
。如果传入的是指针,通过Elem
方法获取指针指向的值。 - 检查值的类型是否为结构体,如果不是则返回错误。
- 遍历结构体的所有字段,将每个字段的值以
interface{}
类型追加到结果切片中。
- 使用
restoreValues
函数:- 使用
switch v := v.(type)
进行类型断言,根据不同类型进行相应处理。 - 如果遇到不支持的类型,打印提示信息。
- 使用
main
函数:- 定义一个
MyStruct
结构体并初始化实例。 - 调用
getFieldsAsInterfaces
获取结构体字段值的interface{}
切片,处理可能的错误。 - 使用
sync.WaitGroup
来同步协程,启动一个新协程调用restoreValues
函数还原值并处理类型断言。
- 定义一个
并发安全
- 数据共享:在这个示例中,
interfaceSlice
是在主协程中生成并传递给新协程的,没有多个协程同时读写该切片,因此不存在数据竞争问题。 - 使用
sync.WaitGroup
:在main
函数中使用sync.WaitGroup
来确保新启动的协程完成后再退出程序,从而保证程序的正确性。
通过以上方式,处理了类型断言可能出现的错误,并保证了在当前场景下的并发安全。