A summary of four types of conversion in golang

Time:2021-5-31

Go type conversion

There are four types of go conversion: assertion, coercion, explicit and implicit.

Generally speaking, type conversion refers to assertion. Coercion is not used in daily life. Display is a basic type conversion. It is used implicitly but not noticed. Assertion, coercion and explicit are described in go syntax, while implicit is summarized in daily use.

Assertion type conversion

Assertions determine whether a variable can be converted to a certain type

Type Asserts

Type assignments syntax document Mirror Address

A simple assertion expression:

var s = x.(T)

If x is not nil and X can be converted to type T, the assertion is successful and the variable s of type T is returned. If t is not an interface type, the type of X is required to be T. If t is an interface, X is required to implement the T interface.

If the assertion type is true, the return value of the expression is x of type T. If the assertion fails, panic will be triggered.

As shown in the above table, if the re assertion fails, it will be panic. Go provides another assertion syntax with whether the return is true or not

s, ok := x.(T)

This method is almost the same as the first one, but OK will return whether the assertion is successful, and no panic will appear. OK means whether it is successful.

Type switch

The go syntax also provides another assertion method of type switch.

Type switches syntax document Mirror Address

If x is asserted as a type, the specific value of type is the value of switch case. If x is successfully asserted as a case type, the case can be executed. At this timei := x.(type)The returned I is the variable of that type, which can be directly used as a case type.

switch i := x.(type) {
case nil:
    printString("x is nil")                // type of i is type of x (interface{})
case int:
    printInt(i)                            // type of i is int
case float64:
    printFloat64(i)                        // type of i is float64
case func(int) float64:
    printFunction(i)                       // type of i is func(int) float64
case bool, string:
    printString("type is bool or string")  // type of i is type of x (interface{})
default:
    printString("don't know the type")     // type of i is type of x (interface{})
}

Force type conversion

Casts are enforced by modifying variable types

This method is not common, mainly used for unsafe package and interface type detection, need to know the go variable knowledge.

unsafe

This document only briefly describes the specific research request to find relevant information.Unsafe syntax document Mirror Address

var f float64
bits = *(*uint64)(unsafe.Pointer(&f))

type ptr unsafe.Pointer
bits = *(*uint64)(ptr(&f))

var p ptr = nil

Float64 is forcibly converted to Uint64 type. The address of float is a value, but the type is float64. Then a Uint64 type variable is created, and the address value is also the address value of float64. The two variables have the same values and different types, so the type is forcibly converted.

Unsafe cast pointer is the underlying operation, with C friends are very familiar with this pointer type conversion, the use ofmemory alignment As like as two peas, int can be converted to uint, and there is a difference between symbol and bit. The value of unsafe conversion may be different, but it is exactly the same in memory storage binary.

Interface type detection

For example, the following code:

var _ Context = (*ContextBase)(nil)

The type of nil is nil, the address value is 0, which is converted to * contextbase by using the mandatory type. The returned variable is the type of * contextbase, the address value is 0, and thenContext=xxIf XX implements the context interface, it will be OK. If XX does not implement the context interface, it will report an error during compilation. During compilation, it will check whether the interface is implemented.

Display type conversion

Conversions syntax document Mirror Address

An explicitly converted expression t (x), where t is a type and X is an expression t that can be converted to a typeuint(666)

The variable x can be converted to type T in any of the following cases:

  • X can be assigned to type T.
  • Ignore that the type of the struct tag X and t have the same base type.
  • Ignore that the type of the struct tag X and T are pointer types of undefined types, and their pointer base types have the same base type.
  • Both the type of X and the type of T are integers or floating-point.
  • The type of X and T are both plural.
  • The type of X is integer or [] byte or [] rune, and t is string type.
  • The type of X is string, and the type of T is [] byte or [] run.

For example, the following code uses rules for conversion, and the rule implementation can refer to the reflect.value.convert method logic:

int64(222)
[]byte("ssss")

type A int
A(2)

Implicit type conversion

Implicit type conversion is not felt in daily use, but it does appear in operation. Two types are listed below.

Re assertion types between combinations

type Reader interface {
    Read(p []byte) (n int, err error)
}
type ReadCloser interface {
    Reader
    Close() error
}
var rc ReaderClose
r := rc

The readerclose interface combines the reader interface, but the assignment of R = RC is still a type conversion. Go uses the built-in function to perform the type conversion. We have encountered variable assignment of similar interface combination type before, and then we found this detail by using pprof and bench tests,Some performance is wasted when transferring interface types

Assignment between the same types

type Handler func()

func NewHandler() Handler {
    return func() {}
}

Although type defines the handler type, handler and func () are two actual types, and the types will not be equal,There are two types of differences when using both reflection and assertion

The two types of verification codes are different

package main

import (
    "fmt"
    "reflect"
)

type Handler func()

func a() Handler {
    return func() {}
}

func main() {
    var i interface{} = main
    _, ok := i.(func())
    fmt.Println(ok)
    _, ok = i.(Handler)
    fmt.Println(ok)
    fmt.Println(reflect.TypeOf(main) == reflect.TypeOf((*Handler)(nil)).Elem())
}

// true
// false
// false

This work adoptsCC agreementReprint must indicate the author and the link of this article

Recommended Today

Supervisor

Supervisor [note] Supervisor – H view supervisor command help Supervisorctl – H view supervisorctl command help Supervisorctl help view the action command of supervisorctl Supervisorctl help any action to view the use of this action 1. Introduction Supervisor is a process control system. Generally speaking, it can monitor your process. If the process exits abnormally, […]