preface

Today the mood is very bad, the company held the game match we were 2 to 0, ah, or silently come over to write….. Let’s briefly write down the reflection and linguistic interactivity of GO

reflection

Reflection is a concept that has rapidly gained popularity since the advent of Java. With reflection, you can capture a wealth of type information and use it to do very flexible work. It’s getting all kinds of information about a class at run time, why do we need reflection, because in many cases, only at run time do we know what class is actually running, what properties are in that class. Go’s reflection does most of what reflection does, but it doesn’t have a built-in type factory like the Java language, so you can’t create object instances from type strings like Java does. Many frameworks in Java have reflection in them, and common Spring /IoC ones rely heavily on reflection.

Reflection in Go requires understanding of two concepts, Type and Value, which are also the two most important types in the Reflect space in Go. Examples are as follows:

Type MyReader struct {Name string} func (r MyReader)Read(p []byte) (n int, err error) {Copy the code

The MyReader type implements all the methods of the IO.Reader interface (which is essentially a Read() function), so MyReader implements the IO. MyReader can be instantiated and assigned as follows:

var reader io.Reader 
reader = &MyReader{"a.txt"}
Copy the code

Reflecting all interfaces yields an information structure containing Type and Value. For example, if we reflect the above example reader, we will get a Type and Value, Type is IO.Reader, Value is MyReader{“a.txt”}. As the name implies, Type mainly represents the reflected Type information of the variable itself, while Value represents the information of the variable instance itself.

Language interactivity

Since the birth of C language, there have been countless new language implementation, but most of the language bottom encapsulates the local method call c language methods, for example, Java provides a JNI mechanism to call those C code libraries, Go language also provides c language call, called Cgo, examples are as follows:

package main

import "fmt"

/*
#include <stdlib.h>
*/
import "C"

func Random() int {
	return int(C.random())
}
func Seed(i int) {
	C.srandom(C.uint(i))
}
func main() {
	Seed(100)
	fmt.Println("Random:", Random())
}
Copy the code

This example calls the RANDOM () and srandom() functions of C, with the following results:

In fact, there is no such thing as a package named C. The import statement is essentially a signal to Cgo that it should start working. What do you do? It is the C source code in the block comments that precedes this import statement that automatically generates the wrapper Go code. From an assembly point of view, a function call is a process of pushing the parameters in order and then making a function call. The code generated by Cgo simply encapsulates the process of pushing and calling what looks like a normal Go function call from the outside.

Type mapping

Type mapping refers to the interaction between two languages, and the conversion relationship of variables between the two languages. For example, the string type of Go language should correspond to the character array of C language, and the life cycle of the object mapped to C language should be long enough to avoid the object being garbage collected during the execution of C language. For C language native types, Cgo will map them to Go language types, know the corresponding relationship.

String mapping

Because Go has an explicit string primitive, and C is represented by character arrays, Cgo provides a series of functions to support it: c.string, c.gostring, and c.gostringn. Note that each conversion of string is a memory copy, and the string cannot be modified. For example, in Java, the concatenation of two values of string is not to modify the original string value, but to allocate new memory space to store the added value. All code using C. string can be written in the following style:

var gostr string // ... Unsafe. Pointer(CSTR)); // Unsafe. unsafe.Pointer(CSTR); C. printf(CSTR, "content is: %d", 123)Copy the code

C program

Any C code that needs to be called in Go can be called in the comments as follows:

package hello 
/* 
#include <stdio.h> 
void hello() { 
 printf("Hello, Cgo! -- From C world.\n"); 
} 
*/ 
import "C" 
func Hello() int { 
 return int(C.hello()) 
}
Copy the code

Cgo provides # Cgo, a pseudo-C grammar, which gives developers the opportunity to specify dependent third-party libraries and compilation options as follows:

// #cgo CFLAGS: -DPNG_DEBUG=1 
// #cgo linux CFLAGS: -DLINUX=1 
// #cgo LDFLAGS: -lpng 
// #include <png.h> 
import "C"
Copy the code

A function call

The normal call is the function name and the argument to be passed. For example, the call with an error return value is:

n, err := C.atoi("a234")
Copy the code

When passing parameters of array types, it is important to note that the address of the first element is passed as the starting address of the entire array in Go, which is not as convenient as passing the array name in C itself. As follows:

N, err := C.f(&array[0]) // The address of the specified first element needs to be displayedCopy the code

Compile the Cgo

Compiling Cgo code is very easy and does not require any special processing. After Go is installed, it comes with a CGO command line tool, which is used to process all Go files with CGO code and generate call encapsulation code of Go language version. The Go toolset encapsulates the CGO command line tool again, enabling the build process to automatically identify and process Go source files with CGO code without any additional work for the user.

note

This article is participating in the “Nuggets Golang Theme Learning Month”. Click here for more details.