欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 财经 > 产业 > Go反射四讲---第四讲:如何使用反射遍历字符串,切片,数组和Map呢?

Go反射四讲---第四讲:如何使用反射遍历字符串,切片,数组和Map呢?

2024/10/24 20:11:58 来源:https://blog.csdn.net/weixin_55818116/article/details/141541474  浏览:    关键词:Go反射四讲---第四讲:如何使用反射遍历字符串,切片,数组和Map呢?

反射-遍历

这是我们反射四讲的第四讲,本次给大家讲解如何使用反射处理一些简单的遍历。

这一讲非常的简单,主要介绍如何遍历数组,切片,字符串,map。

其中,前三种逻辑一致,在遍历map时会有些许不同,不过不用担心,还是很简单的。

数组&切片&字符串

// Iterate 遍历数组,切片,或者字符串
func Iterate(input any) ([]any, error) {val := reflect.ValueOf(input)typ := val.Type()kind := typ.Kind()if kind != reflect.Array && kind != reflect.Slice && kind != reflect.String {return nil, errors.New("input must be array, slice or string")}res := make([]any, 0, val.Len())for i := 0; i < val.Len(); i++ {ele := val.Index(i)if kind == reflect.String {res = append(res, string(ele.Interface().(uint8)))} else {res = append(res, ele.Interface())}}return res, nil
}

测试:

func TestIterate(t *testing.T) {testcases := []struct {name    stringinput   anywantRes []anywantErr error}{{name:    "slicex",input:   []int{1, 2, 3},wantRes: []any{1, 2, 3},},{name:    "array",input:   [3]int{1, 2, 3},wantRes: []any{1, 2, 3},},{name:    "string",input:   "hello",wantRes: []any{"h", "e", "l", "l", "o"},},{name:    "invalid",input:   map[string]int{"a": 1},wantErr: errors.New("input must be array, slicex or string"),},}for _, tt := range testcases {t.Run(tt.name, func(t *testing.T) {res, err := Iterate(tt.input)assert.Equal(t, err, tt.wantErr)assert.Equal(t, tt.wantRes, res)})}
}

Map

在遍历 Map 时,为大家提供两种实现。
第一种:使用 MapRange 提供的迭代器进行遍历。

// IterateMapV1 遍历map
func IterateMapV1(input any) ([]any, []any, error) {val := reflect.ValueOf(input)if val.Kind() != reflect.Map {return nil, nil, errors.New("input must be map")}l := val.Len()keys := make([]any, 0, l)values := make([]any, 0, l)itr := val.MapRange()for itr.Next() {keys = append(keys, itr.Key().Interface())values = append(values, itr.Value().Interface())}return keys, values, nil
}

第二种:使用 MapKeys 提供的 keys 切片进行遍历。

// IterateMapV2 遍历map
func IterateMapV2(input any) ([]any, []any, error) {val := reflect.ValueOf(input)if val.Kind() != reflect.Map {return nil, nil, errors.New("input must be map")}l := val.Len()keys := make([]any, 0, l)values := make([]any, 0, l)for _, key := range val.MapKeys() {keys = append(keys, key.Interface())v := val.MapIndex(key)values = append(values, v.Interface())}return keys, values, nil
}

测试:

func TestIterateMap(t *testing.T) {testcases := []struct {name       stringinput      anywantKeys   []anywantValues []anywantErr    error}{{name:    "nil",input:   nil,wantErr: errors.New("input must be map"),},{name:       "map",input:      map[string]int{"a": 1, "b": 2, "c": 3},wantKeys:   []any{"a", "b", "c"},wantValues: []any{1, 2, 3},},}for _, tt := range testcases {t.Run(tt.name, func(t *testing.T) {keys, values, err := IterateMapV2(tt.input)assert.Equal(t, err, tt.wantErr)assert.Equal(t, tt.wantKeys, keys)assert.Equal(t, tt.wantValues, values)})}
}

反射总结

反射可以让我们去设计一些通用型的代码以及处理方式,并且提供了一种灵活的让程序去自己了解自己和改变自己的能力。但是,反射也有极大的缺点,有时候可能会导致程序崩溃,并且反射代码相对苦涩难懂,不易于理解等。

反射四讲总结

至此,反射四讲完美结束,我平时很喜欢使用 TDD 的流程去开发,所以为大家提供了测试程序。

如果大家想要有一个小项目去实战练习的话,我给大家推荐我之前在ORM层面上实现的元数据的操作,同时也可以帮你练习代码能力。这是项目地址:ORM元数据的设计

最后,总结一下,没有足够的测试,我们一般不要使用反射,因为反射充满了panic

很感谢大家的观看,如果您有宝贵的建议或者想要去了解哪一方面得知识,我很高兴为您讲解。

结束,下期见。

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com