最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Golang泛型實現類型轉換的方法實例

 更新時間:2022年12月30日 11:45:25   作者:戀喵大鯉魚  
將一個值從一種類型轉換到另一種類型,便發(fā)生了類型轉換,下面這篇文章主要給大家介紹了關于Golang泛型實現類型轉換的相關資料,文中通過實例代碼介紹的非常詳細,需要的朋友可以參考下

1.前言

Golang 標準庫提供了很多類型轉換的函數,如 strconv 包可完成 string 與基本數據類型之間的轉換。

比如將 int 與 string 之間的互轉。

// int to string
s := strconv.Itoa(i)

// string to int
i, err := strconv.ParseInt(i, 0, 64)

如果我們想完成任意類型到某一具體類型的轉換,該如何實現呢?

2.To String

以 string 為,我們可以這樣實現。

// ToStringE casts any type to a string type.
func ToStringE(i any) (string, error) {
	i = indirectToStringerOrError(i)

	switch s := i.(type) {
	case string:
		return s, nil
	case bool:
		return strconv.FormatBool(s), nil
	case float64:
		return strconv.FormatFloat(s, 'f', -1, 64), nil
	case float32:
		return strconv.FormatFloat(float64(s), 'f', -1, 32), nil
	case int:
		return strconv.Itoa(s), nil
	case int64:
		return strconv.FormatInt(s, 10), nil
	case int32:
		return strconv.Itoa(int(s)), nil
	case int16:
		return strconv.FormatInt(int64(s), 10), nil
	case int8:
		return strconv.FormatInt(int64(s), 10), nil
	case uint:
		return strconv.FormatUint(uint64(s), 10), nil
	case uint64:
		return strconv.FormatUint(uint64(s), 10), nil
	case uint32:
		return strconv.FormatUint(uint64(s), 10), nil
	case uint16:
		return strconv.FormatUint(uint64(s), 10), nil
	case uint8:
		return strconv.FormatUint(uint64(s), 10), nil
	case json.Number:
		return s.String(), nil
	case []byte:
		return string(s), nil
	case template.HTML:
		return string(s), nil
	case template.URL:
		return string(s), nil
	case template.JS:
		return string(s), nil
	case template.CSS:
		return string(s), nil
	case template.HTMLAttr:
		return string(s), nil
	case nil:
		return "", nil
	case fmt.Stringer:
		return s.String(), nil
	case error:
		return s.Error(), nil
	default:
		return "", fmt.Errorf("unable to cast %#v of type %T to string", i, i)
	}
}

其中 indirectToStringerOrError 是對指針類型的解引用,從標準庫 html/template/content.go 獲取。

var (
	errorType       = reflect.TypeOf((*error)(nil)).Elem()
	fmtStringerType = reflect.TypeOf((*fmt.Stringer)(nil)).Elem()
)

// Copied from html/template/content.go.
// indirectToStringerOrError returns the value, after dereferencing as many times
// as necessary to reach the base type (or nil) or an implementation of fmt.Stringer
// or error,
func indirectToStringerOrError(a any) any {
	if a == nil {
		return nil
	}
	v := reflect.ValueOf(a)
	for !v.Type().Implements(fmtStringerType) && !v.Type().Implements(errorType) && v.Kind() == reflect.Pointer && !v.IsNil() {
		v = v.Elem()
	}
	return v.Interface()
}

3.To Other Type

那么對其他類型我們也都要實現對應的轉換函數。

// ToBoolE casts any type to a bool type.
func ToBoolE(i any) (bool, error) {
	i = indirect(i)

	switch b := i.(type) {
	case bool:
		return b, nil
	case nil:
		return false, nil
	case int:
		if i.(int) != 0 {
			return true, nil
		}
		return false, nil
	case string:
		return strconv.ParseBool(i.(string))
	default:
		return false, fmt.Errorf("unable to cast %#v of type %T to bool", i, i)
	}
}

// ToIntE, ToInt8E, ToInt16E...

3.泛型

最終,我們可以通過泛型完成對上面多個具體類型轉換函數的封裝。這樣我們只需要調用一個函數,便可完成對所有類型的轉換。

// ToAnyE converts one type to another and returns an error if occurred.
func ToAnyE[T any](a any) (T, error) {
	var t T
	switch any(t).(type) {
	case bool:
		v, err := ToBoolE(a)
		if err != nil {
			return t, err
		}
		t = any(v).(T)
	case int:
		v, err := ToIntE(a)
		if err != nil {
			return t, err
		}
		t = any(v).(T)
	case int8:
		v, err := ToInt8E(a)
		if err != nil {
			return t, err
		}
		t = any(v).(T)
	case int16:
		v, err := ToInt16E(a)
		if err != nil {
			return t, err
		}
		t = any(v).(T)
	case int32:
		v, err := ToInt32E(a)
		if err != nil {
			return t, err
		}
		t = any(v).(T)
	case int64:
		v, err := ToInt64E(a)
		if err != nil {
			return t, err
		}
		t = any(v).(T)
	case uint:
		v, err := ToUintE(a)
		if err != nil {
			return t, err
		}
		t = any(v).(T)
	case uint8:
		v, err := ToUint8E(a)
		if err != nil {
			return t, err
		}
		t = any(v).(T)
	case uint16:
		v, err := ToUint16E(a)
		if err != nil {
			return t, err
		}
		t = any(v).(T)
	case uint32:
		v, err := ToUint32E(a)
		if err != nil {
			return t, err
		}
		t = any(v).(T)
	case uint64:
		v, err := ToUint64E(a)
		if err != nil {
			return t, err
		}
		t = any(v).(T)
	case float32:
		v, err := ToFloat32E(a)
		if err != nil {
			return t, err
		}
		t = any(v).(T)
	case float64:
		v, err := ToFloat64E(a)
		if err != nil {
			return t, err
		}
		t = any(v).(T)
	case string:
		v, err := ToStringE(a)
		if err != nil {
			return t, err
		}
		t = any(v).(T)
	default:
		return t, fmt.Errorf("the type %T is not supported", t)
	}
	return t, nil
}

如果不關心錯誤,可以再封裝一下。

// ToAny converts one type to another type.
func ToAny[T any](a any) T {
	v, _ := ToAnyE[T](a)
	return v
}

4.使用示例

package main

import (
	"fmt"
)

func main() {
	fmt.Println(ToAny[string](1))    // "1"
	fmt.Println(ToAny[string](true)) // "true"
	fmt.Println(ToAny[string](1.1))  // "1.1"

	fmt.Println(ToAny[int]("1"))   	// 1
	fmt.Println(ToAny[int]("1.0")) 	// 1
	fmt.Println(ToAny[int](true))  	// 1

	fmt.Println(ToAny[bool]("true"))  // true
	fmt.Println(ToAny[bool]("false")) // false
	fmt.Println(ToAny[bool]("True"))  // true
	fmt.Println(ToAny[bool]("False")) // false
	fmt.Println(ToAny[bool](1))       // true
	fmt.Println(ToAny[bool](0))       // false
	fmt.Println(ToAny[bool](nil))     // false
}

5.go-huge-util

為了方便大家使用,以上相關代碼已開源至 Github 工具庫 go-huge-util,大家可使用 go mod 方式 import 然后使用。

import "github.com/dablelv/go-huge-util/conv"

conv.ToAny[string](1)    // "1"
conv.ToAny[string](true) // "true"
conv.ToAny[string](1.1)  // "1.1"

conv.ToAny[int]("1")   // 1
conv.ToAny[int]("1.0") // 1
conv.ToAny[int](true)  // 1

conv.ToAny[bool]("true")  // true
conv.ToAny[bool]("false") // false
conv.ToAny[bool]("True")  // true
conv.ToAny[bool]("False") // false
conv.ToAny[bool](1)       // true
conv.ToAny[bool](0)       // false
conv.ToAny[bool](nil)     // false

go-huge-util 除了類型轉換,還有很多其他實用函數,如加解密、zip 等,歡迎大家使用、Star 和 Pull Request。

參考文獻

github.com/dablelv/go-huge-util

總結

到此這篇關于Golang泛型實現類型轉換的文章就介紹到這了,更多相關Golang泛型類型轉換內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • golang如何使用gomobile進行Android開發(fā)

    golang如何使用gomobile進行Android開發(fā)

    golang可以開發(fā)android,使用golang開發(fā)android需要下載安裝gomobile,下面這篇文章主要給大家介紹了關于golang如何使用gomobile進行Android開發(fā)的相關資料,需要的朋友可以參考下
    2023-01-01
  • 優(yōu)雅使用GoFrame共享變量Context示例詳解

    優(yōu)雅使用GoFrame共享變量Context示例詳解

    這篇文章主要為大家介紹了優(yōu)雅使用GoFrame共享變量Context示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-06-06
  • 超全講解Golang中defer關鍵字的用法

    超全講解Golang中defer關鍵字的用法

    本文將從一個資源回收問題引入,引出defer關鍵字,并對其進行基本介紹,從而讓大家對Go語言中的defer有更深入的了解,需要的小伙伴可以學習一下
    2023-05-05
  • 源碼解析gtoken替換jwt實現sso登錄

    源碼解析gtoken替換jwt實現sso登錄

    這篇文章主要為大家介紹了源碼解析gtoken替換jwt實現sso登錄的示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-06-06
  • golang gorm 操作mysql及gorm基本用法

    golang gorm 操作mysql及gorm基本用法

    golang 官方的那個操作mysql的有點麻煩所以就使用了gorm,下面就gorm的使用做下簡單介紹,感興趣的朋友跟隨小編一起看看吧
    2018-11-11
  • Go語言上下文context底層原理

    Go語言上下文context底層原理

    這篇文章主要介紹了Go語言上下文context底層原理,context是Go中用來進程通信的一種方式,其底層是借助channl與snyc.Mutex實現的,更多相關內容需要的小伙伴可以參加一下
    2022-06-06
  • 如何使用騰訊云go sdk 查詢對象存儲中最新文件

    如何使用騰訊云go sdk 查詢對象存儲中最新文件

    這篇文章主要介紹了使用騰訊云go sdk 查詢對象存儲中最新文件,這包括如何創(chuàng)建COS客戶端,如何逐頁檢索對象列表,并如何對結果排序以找到最后更新的對象,我們還展示了如何優(yōu)化用戶體驗,通過實時進度更新和檢索多個文件來改進程序,需要的朋友可以參考下
    2024-03-03
  • Golang實現常見的限流算法的示例代碼

    Golang實現常見的限流算法的示例代碼

    限流是項目中經常需要使用到的一種工具,一般用于限制用戶的請求的頻率,也可以避免瞬間流量過大導致系統(tǒng)崩潰,或者穩(wěn)定消息處理速率,本文主要介紹了使用Go實現常見的限流算法,希望對大家有所幫助
    2023-04-04
  • go module使用本地包的方法示例

    go module使用本地包的方法示例

    這篇文章主要介紹了go module使用本地包的方法示例,小編覺得挺不錯的,現在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2019-03-03
  • go開源Hugo站點渲染之模板詞法解析

    go開源Hugo站點渲染之模板詞法解析

    這篇文章主要為大家介紹了go開源Hugo站點渲染之模板詞法解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-02-02

最新評論

喀喇| 桂平市| 安新县| 文登市| 清水河县| 五家渠市| 曲阜市| 平定县| 绵竹市| 翁牛特旗| 万源市| 玉龙| 繁昌县| 孟州市| 嘉鱼县| 昌宁县| 博客| 太仓市| 苍山县| 泗阳县| 霍山县| 禹城市| 晋中市| 吴江市| 高陵县| 新乡县| 丹寨县| 定安县| 无极县| 福州市| 太原市| 行唐县| 苍山县| 丹寨县| 邯郸市| 中牟县| 鹰潭市| 辛集市| 汉川市| 建瓯市| 噶尔县|