Какво прави go generate ./...? Как?
//go:generate command --args
Къде можете да видите документацията на gitlab.com/ivan/libawesome?
Кога работи вградения race detector? Как се ползва?
go test -racego run -racego build -racego install -raceКак мога да направя файл в пакет, който се build-ва само в Линукс?
// +build linux в началото му*_linux.gopackage 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.uintC.struct_fooerrnon, 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);
}gccgoall: 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) uintptrfunc Offsetof(v ArbitraryType) uintptrfunc Sizeof(v ArbitraryType) uintptrtype ArbitraryType inttype 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 assemstrtolower 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
endident 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)
RETTEXT add(SB), $0-24
MOVQ b+16(FP), AX
MOVQ a+8(FP), CX
ADDQ CX, AX
MOVQ AX, 24(FP)
RETTEXT add(SB), $-8-24
MOVD a(FP), R0
MOVD b+8(FP), R1
ADD R1, R0
MOVD R0, 16(FP)
RETTEXT add(SB), $0-24
MOVD a(FP), R1
MOVD b+8(FP), R2
ADD R2, R1, R1
MOVD R1, 16(FP)
RETTEXT add(SB), $0-24
MOVD a(FP), R2
MOVD b+8(FP), R3
ADD R3, R2
MOVD R2, 16(FP)
RETНа практика са еднакви.
real -> go assemblygithub.com/golang/go/blob/master/src/cmd/internal/obj/arm64/asm7.go
export GODEBUG="name=flag"
Пример:
export GODEBUG="gctrace=2,invalidptr=1"
Позволява:
GOGC=100GOGC=off спира събирането на боклук изцялоGOMAXPROCS(n int) от пакета runtime