در Go، تبدیل بین نوعهای مختلف باید صریح باشد.
تبدیل بین نوعها (که به آن تبدیل نوع هم میگویند) از طریق تابعی انجام میشود که اسم نوع مقصد را دارد.
برای نمونه، برای تبدیل یک int به float64 باید به این شکل عمل کنید:
var x int = 42 // x has type int
f := float64(x) // f has type float64 (ie. 42.0)
بستهای به نام strconv برای تبدیل بین نوعهای پایه (مثل int) و string وجود دارد.
import "strconv"
var intString string = "42"
var i, err = strconv.Atoi(intString)
var number int = 12
var s string = strconv.Itoa(number)
رابطها در Go میتوانند دربارهی نوع زیرین ابهام ایجاد کنند.
تأیید نوع به ما اجازه میدهد تا مقدار مشخص زیرینِ مقدار رابط را با این نحوهی نگارش بیرون بکشیم: interfaceVariable.(concreteType).
برای نمونه:
var input any = 12
number := input.(int)
توجه: اگر متغیر رابط مقداری از نوع مشخص را نگه ندارد، این کار باعث panic میشود.
میتوانیم با استفاده از هر دو مقدار بازگشتی تأیید نوع بررسی کنیم که آیا مقدار رابط یک نوع مشخص خاص را نگه میدارد یا نه: مقدار زیرین و یک «مقدار منطقی» که گزارش میدهد آیا تأیید موفق بوده است یا نه. برای نمونه:
str, ok := input.(string) // no panic if input is not a string
اگر input یک string نگه دارد، str مقدار زیرین خواهد بود و ok برابر با «درست» خواهد بود.
اگر input یک string نگه ندارد، str مقدار صفر نوع string خواهد بود (یعنی ""، رشتهی خالی) و ok برابر با «غلط» خواهد بود.
در هیچ حالتی panic رخ نمیدهد.
یک سوئیچ نوع میتواند چندین تأیید نوع را پشت سر هم انجام دهد.
نحوهی نگارش آن همانند تأیید نوع است (interfaceVariable.(concreteType))، اما concreteType با کلیدواژهی type جایگزین میشود.
برای نمونه:
var i any = 12 // try: 12.3, true, int64(12), []int{}, map[string]int{}
switch v := i.(type) {
case int:
fmt.Printf("the integer %d\n", v)
case string:
fmt.Printf("the string %s\n", v)
default:
fmt.Printf("type, %T, not handled explicitly: %#v\n", v, v)
}
جِن در اتاق مرتبسازی یک کارخانهی بزرگ کار میکند. اتاق مرتبسازی باید هر چه را که واردش میشود پردازش کند و آن را با یک برچسب دستهبندی کند. جِن مسئول مواردی است که از پیش به عنوان عدد دستهبندی شدهاند. او به برنامهای نیاز دارد که در مرتبسازی کمکش کند.
بیشتر مقادیر اولیه باید برچسبهای سرراستی بگیرند.
برای اعداد، او رشتههایی میخواهد که بگویند "This is the number 2.0" (اگر عدد ۲ بود).
جِن برای اعداد صحیح و اعداد اعشاری همین خروجی را میخواهد.
چند رابط Box وجود دارد که باید بازگشایی شوند تا محتوایشان به دست بیاید.
برای یک NumberBox، او رشتههایی میخواهد که بگویند "This is a box containing the number 3.0" (اگر متد Number() مقدار ۳ را برگرداند).
برای یک FancyNumberBox، او رشتههایی میخواهد که بگویند "This is a fancy box containing the number 4.0"، اما فقط اگر نوع آن FancyNumber باشد.
هر مورد غیرمنتظرهای باید بگوید "Return to sender" تا جِن بتواند آنها را به همان جایی که از آن آمدهاند پس بفرستد.
جِن میخواهد اعداد رشتههایی مانند "This is the number 2.0" برگردانند (با یک رقم پس از ممیز):
fmt.Println(DescribeNumber(-12.345))
// Output: This is the number -12.3
جِن میخواهد جعبههای عدد رشتههایی مانند "This is a box containing the number 2.0" برگردانند (باز هم با یک رقم پس از ممیز):
fmt.Println(DescribeNumberBox(numberBoxContaining{12}))
// Output: This is a box containing the number 12.0
جِن به یک تابع کمکی نیاز دارد که عدد را از یک FancyNumberBox بیرون بکشد.
اگر FancyNumberBox از نوع FancyNumber باشد، مقدارش را استخراج کنید و آن را از string به int تبدیل کنید.
هر نوع دیگری از FancyNumberBox باید ۰ را برگرداند.
fmt.Println(ExtractFancyNumber(FancyNumber{"10"}))
// Output: 10
fmt.Println(ExtractFancyNumber(AnotherFancyNumber{"4"}))
// Output: 0
اگر FancyNumberBox از نوع FancyNumber باشد، جِن رشتههایی میخواهد که بگویند "This is a fancy box containing the number 4.0".
هر نوع دیگری از FancyNumberBox باید بگوید "This is a fancy box containing the number 0.0".
fmt.Println(DescribeFancyNumberBox(FancyNumber{"10"}))
// Output: This is a fancy box containing the number 10.0
fmt.Println(DescribeFancyNumberBox(AnotherFancyNumber{"4"}))
// Output: This is a fancy box containing the number 0.0
توجه: باید از تابع ExtractFancyNumber استفاده کنیم!
DescribeAnything که از همهی آنها استفاده میکنداین همان تابع اصلی است که جِن نیاز دارد و هر ورودیای را میپذیرد.
DescribeAnything باید بر اساس نوع مقداری که به آن داده میشود، کار را به توابع دیگر واگذار کند.
به طور مشخص:
int و float64 هر دو باید به DescribeNumber واگذار کنندNumberBox باید به DescribeNumberBox واگذار کندFancyNumberBox باید به DescribeFancyNumberBox واگذار کند"Return to sender" برگردانده شودfmt.Println(DescribeAnything(numberBoxContaining{12.345}))
// Output: This is a box containing the number 12.3
fmt.Println(DescribeAnything("some string"))
// Output: Return to sender