Какво прави go generate ./...
? Как?
//go:generate command --args
Къде можете да видите документацията на gitlab.com/ivan/libawesome
?
Кога работи вградения race detector? Как се ползва?
go test -race
go run -race
go build -race
go install -race
Как мога да направя файл в пакет, който се build-ва само в Линукс?
// +build linux
в началото му*_linux.go
package main /* #include <stdlib.h> */ import "C" func Random() int { return int(C.random()) } func Seed(i int) { C.srandom(C.uint(i)) }
#cgo
са "специални"// #cgo CFLAGS: -DPNG_DEBUG=1 // #cgo amd64 386 CFLAGS: -DX86=1 // #cgo LDFLAGS: -lpng // #include <png.h> import "C"
// #cgo pkg-config: png cairo
package goc import "C" //export GreetFromGo func GreetFromGo(name string) { println("Hello from Go, ", name) } func main() { // Needed by cgo in order to generate a library }
go build -buildmode=c-archive -o goc.a goc.go
goc.a
и goc.h
файловеgoc.h
, освен малко boilerplate, ще има и:extern void GreetFromGo(GoString p0);
GoString
е част от споменатия boilerplate#include "goc.h" #include <stdio.h> int main() { printf("Hi, I am a C program.\n"); GoString name = {"Doycho", 4}; GreetFromGo(name); return 0; }
gcc -pthread -o out goc.c goc.a
Стигне ли се до компилиране на C, забравете за лесно:
Но, за това пък, има много от:
Споделяне на памет, алокирана от Go е възможно ако:
runtime проверява за това и ако види нарушение crash-ва програмата.
unsigned int
-> C.uint
C.struct_foo
errno
n, err := C.sqrt(-1)
package main // typedef int (*intFunc) (); // // int // bridge_int_func(intFunc f) // { // return f(); // } // // int fortytwo() // { // return 42; // } import "C" import "fmt" func main() { f := C.intFunc(C.fortytwo) fmt.Println(int(C.bridge_int_func(f))) // Output: 42 }
package main func Add(a, b int) int { return a + b }
#include <stdio.h> extern int go_add(int, int) __asm__ ("example.main.Add"); int main() { int x = go_add(2, 3); printf("Result: %d\n", x); }
gccgo
all: main main: foo.o bar.c gcc foo.o bar.c -o main foo.o: foo.go gccgo -c foo.go -o foo.o -fgo-prefix=example clean: rm -f main *.o
Декларира невинно изглеждащите:
func Alignof(v ArbitraryType) uintptr
func Offsetof(v ArbitraryType) uintptr
func Sizeof(v ArbitraryType) uintptr
type ArbitraryType int
type Pointer *ArbitraryType
реално тези дефиниции съществуват главно за документация, имплементацията е в компилатора.
unsafe.Pointer има четири важни харектеристики
Това е практическо заобикаляне на типовата система в Go.
package main /* #include <stdlib.h> */ import "C" import ( "fmt" "unsafe" ) func main() { cs := C.CString("42") // alloc on C's heap defer C.free(unsafe.Pointer(cs)) // don't leak answer := C.atoi(cs) fmt.Println(answer) }
package main
import "unsafe"
import "fmt"
type slice struct { array unsafe.Pointer size, _cap int } func main() { var p = []string{"Hello", " "} p = append(p, "World!") var s = (*slice)(unsafe.Pointer(&p)) var sizeOfString = unsafe.Sizeof("") fmt.Printf("size=%d, cap=%d\n", s.size, s._cap) for i := 0; s.size > i; i++ { fmt.Printf("[%d]: `%s`\n", i, *(*string)(unsafe.Pointer(uintptr(s.array) + uintptr(i)*sizeOfString))) } }
1 PRINT NOGEN 2 STOCK1 START 0 3 BEGIN BALR 11,0 4 USING *,11 5 MVC NEWOH,OLDOH 6 AP NEWOH,RECPT 7 AP NEWOH,ISSUE 8 EOJ 11 OLDOH DC PL4'9' 12 RECPT DC PL4'4' 13 ISSUE DC PL4'6' 14 NEWOH DS PL4 15 END BEGIN
# TO ENTER A JOB REQUEST REQUIRING NO VAC AREA: COUNT 02/EXEC NOVAC INHINT AD FAKEPRET # LOC(MPAC +6) - LOC(QPRET) TS NEWPRIO # PRIORITY OF NEW JOB + NOVAC C(FIXLOC) EXTEND INDEX Q # Q WILL BE UNDISTURBED THROUGHOUT. DCA 0 # 2CADR OF JOB ENTERED. DXCH NEWLOC CAF EXECBANK XCH FBANK TS EXECTEM1 TCF NOVAC2 # ENTER EXECUTIVE BANK.
Маргарет Хамилтън
TITLE COUNT A=1 ;Define a name for an accumulator. START: MOVSI A,-100 ;initialize loop counter. ;A contains -100,,0 LOOP: HRRZM A,TABLE(A) ;Use right half of A to index. AOBJN A,LOOP ;Add 1 to both halves (-77,,1 -76,,2 etc.) ;Jump if still negative. .VALUE ;Halt program. TABLE: BLOCK 100 ;Assemble space to fill up. END START ;End the assembly.
/ a3 -- pdp-11 assembler pass 1 assem: jsr pc,readop jsr pc,checkeos br ealoop tst ifflg beq 3f cmp r4,$200 blos assem cmpb (r4),$21 /if bne 2f inc ifflg 2: cmpb (r4),$22 /endif bne assem dec ifflg br assem
strtolower public link a6,#0 ;Set up stack frame movea 8(a6),a0 ;A0 = src, from stack movea 12(a6),a1 ;A1 = dst, from stack loop move.b (a0)+,d0 ;Load D0 from (src) cmpi #'A',d0 ;If D0 < 'A', blo copy ;skip cmpi #'Z',d0 ;If D0 > 'Z', bhi copy ;skip addi #'a'-'A',d0 ;D0 = lowercase(D0) copy move.b d0,(a1)+ ;Store D0 to (dst) bne loop ;Repeat while D0 <> NUL unlk a6 ;Restore stack frame rts ;Return end
ident slice V6 0 ; initialize S A4 S0 ; initialize *x A5 S1 ; initialize *y A3 S2 ; initialize i loop S0 A3 JSZ exit ; if S0 == 0 goto exit VL A3 ; set vector length V11 ,A4,1 ; load slice of x[i], stride 1 V12 ,A5,1 ; load slice of y[i], stride 1 V13 V11 *F V12 ; slice of x[i] * y[i] V6 V6 +F V13 ; partial sum A14 VL ; get vector length of this iteration A4 A4 + A14 ; *x = *x + VL A5 A5 + A14 ; *y = *y + VL A3 A3 - A14 ; i = i - VL J loop exit
Имат доста обща структура:
subroutine header label: instruction operand... ; comment ...
Чрез собствен assembler, който след това лесно се превежда до реалния на всяка машина.
Нека разгледаме go програмата
package add func add(a, b int) int { return a + b }
И сега генерирания assembly
TEXT add(SB), $0-12 MOVL a+4(FP), BX ADDL b+8(FP), BX MOVL BX, 12(FP) RET
TEXT add(SB), $0-24 MOVQ b+16(FP), AX MOVQ a+8(FP), CX ADDQ CX, AX MOVQ AX, 24(FP) RET
TEXT add(SB), $-8-24 MOVD a(FP), R0 MOVD b+8(FP), R1 ADD R1, R0 MOVD R0, 16(FP) RET
TEXT add(SB), $0-24 MOVD a(FP), R1 MOVD b+8(FP), R2 ADD R2, R1, R1 MOVD R1, 16(FP) RET
TEXT add(SB), $0-24 MOVD a(FP), R2 MOVD b+8(FP), R3 ADD R3, R2 MOVD R2, 16(FP) RET
На практика са еднакви.
real -> go assembly
github.com/golang/go/blob/master/src/cmd/internal/obj/arm64/asm7.go
export GODEBUG="name=flag"
Пример:
export GODEBUG="gctrace=2,invalidptr=1"
Позволява:
GOGC=100
GOGC=off
спира събирането на боклук изцялоGOMAXPROCS(n int)
от пакета runtime