Next, let's try something that would write out some data - extracting the first page of PDF to first_page.pdf (see go.argv below), in index.html:

function done() {
        const go = new Go();
        WebAssembly.instantiateStreaming(fetch("pdfcpu.wasm"), go.importObject).then((result) => {
            go.argv = ['pdfcpu.wasm', 'trim', '-pages', '1', '/test.pdf', '/first_page.pdf'];
            var st = Date.now();
            go.run(result.instance);
            console.log('Time taken:', Date.now() - st);
            fs.readFile('/first_page.pdf', function(err, contents) {
                console.log("after run main:", err, contents);
            });
        });
    }
Goroutines are the basic building block for concurrency in the Go language. They are green threads – lightweight threads managed by the Go runtime, not by the operating system. This means you can run thousands (or millions) of them without any significant overhead. Goroutines are spawned with the go keyword, and always start with a function (or method call):

// Returns immediately, without waiting for `DoSomething()` to complete
go DoSomething()
From the Go documentation, it's possible to execute the wasm file using Node.js. It requires running a js file called wasm_exec.js located in misc/wasm directory of your Go installation (eg: /usr/local/go/misc/wasm, NOTE the js file must match the same version of Go used to compile the wasm file, so you can't just grab the latest wasm_exec.js from the golang Github repo and expect it to work), so let's confirm that:

cp /usr/local/go/misc/wasm/wasm_exec.js ./
node wasm_exec.js pdfcpu.wasm version
All of this means that although our benchmark is now concurrent, it isn’t parallel. Only one of our workers will run at a time, and it will run until it’s done. We can change this by telling Go to use more threads, via the GOMAXPROCS environment variable.

$ GOMAXPROCS=4 go test -bench . funding
BenchmarkWithdrawals-4    --- FAIL: BenchmarkWithdrawals-4
    account_test.go:39: Balance wasn't zero: 4238
ok      funding    0.007s
To see what gets put in the binary after linking, use go tool objdump:

$ go build -o x.exe x.go
$ go tool objdump -s main.main x.exe
TEXT main.main(SB) /tmp/x.go
  x.go:3		0x10501c0		65488b0c2530000000	MOVQ GS:0x30, CX
  x.go:3		0x10501c9		483b6110		CMPQ 0x10(CX), SP
  x.go:3		0x10501cd		7634			JBE 0x1050203
  x.go:3		0x10501cf		4883ec10		SUBQ $0x10, SP
  x.go:3		0x10501d3		48896c2408		MOVQ BP, 0x8(SP)
  x.go:3		0x10501d8		488d6c2408		LEAQ 0x8(SP), BP
  x.go:4		0x10501dd		e86e45fdff		CALL runtime.printlock(SB)
  x.go:4		0x10501e2		48c7042403000000	MOVQ $0x3, 0(SP)
  x.go:4		0x10501ea		e8e14cfdff		CALL runtime.printint(SB)
  x.go:4		0x10501ef		e8ec47fdff		CALL runtime.printnl(SB)
  x.go:4		0x10501f4		e8d745fdff		CALL runtime.printunlock(SB)
  x.go:5		0x10501f9		488b6c2408		MOVQ 0x8(SP), BP
  x.go:5		0x10501fe		4883c410		ADDQ $0x10, SP
  x.go:5		0x1050202		c3			RET
  x.go:3		0x1050203		e83882ffff		CALL runtime.morestack_noctxt(SB)
  x.go:3		0x1050208		ebb6			JMP main.main(SB)
We started thinking we should look at full core dumps or maybe there were hanging connections or go routines when making the requests to the Elastic cluster. So we looked at the goroutine profile of pprof:

curl https://services/domain-service/debug/pprof/goroutine > goroutine.out
go tool pprof goroutine.out
The header file defines C types mapped to Go compatible types using cgo semantics.

/* Created by “go tool cgo” – DO NOT EDIT. */
...
typedef long long GoInt64;
typedef unsigned long long GoUint64;
typedef GoInt64 GoInt;
typedef double GoFloat64;
...
typedef struct { const char *p; GoInt n; } GoString;
typedef struct { void *data; GoInt len; GoInt cap; } GoSlice;
...
#endif
...
extern GoInt Add(GoInt p0, GoInt p1);
extern GoFloat64 Cosine(GoFloat64 p0);
extern void Sort(GoSlice p0);
extern GoInt Log(GoString p0);
...
fund.go

package funding

type Fund struct {
    // balance is unexported (private), because it's lowercase
    balance int
}

// A regular function returning a pointer to a fund
func NewFund(initialBalance int) *Fund {
    // We can return a pointer to a new struct without worrying about
    // whether it's on the stack or heap: Go figures that out for us.
    return &Fund{
        balance: initialBalance,
    }
}

// Methods start with a *receiver*, in this case a Fund pointer
func (f *Fund) Balance() int {
    return f.balance
}

func (f *Fund) Withdraw(amount int) {
    f.balance -= amount
}
server.go

package funding

type FundServer struct {
    Commands chan interface{}
    fund Fund
}

func NewFundServer(initialBalance int) *FundServer {
    server := &FundServer{
        // make() creates builtins like channels, maps, and slices
        Commands: make(chan interface{}),
        fund: NewFund(initialBalance),
    }

    // Spawn off the server's main loop immediately
    go server.loop()
    return server
}

func (s *FundServer) loop() {
    // The built-in "range" clause can iterate over channels,
    // amongst other things
    for command := range s.Commands {
    
        // Handle the command
        
    }
}
Now that you have a dependency on an external module, you need to download that module and record its version in your go.mod file. The go mod tidy command adds missing module requirements for imported packages and removes requirements on modules that aren't used anymore.

$ go mod tidy
go: finding module for package github.com/google/go-cmp/cmp
go: found github.com/google/go-cmp/cmp in github.com/google/go-cmp v0.5.4
$ go install example/user/hello
$ hello
Hello, Go!
  string(
- 	"Hello World",
+ 	"Hello Go",
  )
$ cat go.mod
module example/user/hello

go 1.16

require github.com/google/go-cmp v0.5.4
$

Recommend

Browser-side PDF processing with Go and WebAssembly

mysql 执行大量insert语句

C if 语句 实例

C if 语句 语法

并发编程网 - ifeve.com 控制并发阶段性任务的改变

12306的西天取经路 - 春节抢票与PostgreSQL数据库设计思考 二、谁是猴子请来的救兵?

12306的西天取经路 - 春节抢票与PostgreSQL数据库设计思考 一、铁路售票系统 - 西天取经之路开始啦

C 库函数 - abort() 实例

C 库函数 - abort() 声明

并发编程网 - ifeve.com 让天下没有难学的技术 颠覆大数据分析之Storm简介

并发编程网 - ifeve.com 让天下没有难学的技术 定制并发类(十)实现一个基于优先级的传输队列

如何从零写一个正则表达式引擎? 30 个回答

史上最LOW的PHP连接池解决方案

三、远程服务调用 3.1 简单使用

二、远程服务暴露 2.1 简单使用

并发编程网 - ifeve.com 标签 ‘ Scala ’ 话说模式匹配(5) for表达式中的模式匹配

并发编程网 - ifeve.com 标签 ‘ Scala ’ 话说模式匹配(6) case类的细节

并发编程网 - ifeve.com 标签 ‘ Scala ’ 话说模式匹配(7) 一个构造器模式的例子(by case class)

并发编程网 - ifeve.com 标签 ‘ Scala ’ 话说模式匹配(8) 一个抽取器的例子

并发编程网 - ifeve.com 作者归档 《Python3.6官方文档》– 第二章 使用python解释器 2.1. 调用解释器

并发编程网 - ifeve.com 3 设计与实现

js 实现数值的千分位及保存小数方法

菜鸟教程 -- 学的不仅是技术,更是梦想! 2.使用示例: 示例二:在指定地方播放帧动画

菜鸟教程 -- 学的不仅是技术,更是梦想! 2.使用示例: 示例一:最简单的例子:

LIBUCL Performance

LIBUCL General improvements Single quoted strings

LIBUCL General improvements Multiline strings

LIBUCL General improvements Macros support

LIBUCL General improvements Comments

LIBUCL Improvements to the json notation. Named keys hierarchy

LIBUCL Improvements to the json notation. Automatic arrays creation

LIBUCL Improvements to the json notation. General syntax sugar

LIBUCL Basic structure

并发编程网 - ifeve.com 让天下没有难学的技术 讨喜的隔离可变性(六)多角色协作