Running Golang Programs on the Duo Development Board

Go language offers many advantages in the field of network programming. Its outstanding concurrency model and concise syntax make it an ideal choice for building efficient network applications. Firstly, Go’s built-in goroutines and channel mechanisms simplify concurrent programming, allowing the easy creation of a large number of concurrent tasks within a program without the need for extensive thread management and locks. This results in more efficient resource utilization and faster response times.

Secondly, the rich network packages in Go’s standard library, including implementations of protocols like TCP, UDP, and HTTP in the net package, provide strong support for network programming, making it easier for developers to build network applications.

Furthermore, Go language’s benefits as a compiled language allow it to generate efficient machine code, which leads to excellent performance in network applications. Its robust error-handling mechanisms and built-in testing framework help build stable and maintainable network applications.

In conclusion, Go’s support for concurrency, rich network libraries, and strong performance make it an excellent choice for building high-performance and reliable network applications.

I. Running a Golang “Hello World” Program

Here’s a simple example of a Hello World program in Go:

package main

import "fmt"

func main() {
    fmt.Println("Hello, World!")
}

You can save the above code in a file with a .go extension, such as hello.go. Then, navigate to the directory where the file is located in the terminal and use the following command to compile and run the program:

go run hello.go

After running the command, you will see the output in the terminal:

Hello, World!

Since the Go package downloaded from the official Go website may not run on the development board, it’s recommended to try cross-compiling.

II. On an x86 platform with Linux, you can cross-compile a Go program as follows:

CGO_ENABLED=0 GOARCH=riscv64 go build -ldflags="-s -w" -o helloG hello.go

You can then upload this binary to the development board for testing.

If you encounter any error messages, please provide the specific error message for further assistance.

[root@milkv]~# ./helloG 
runtime: epollcreate failed with 38
fatal error: runtime: netpollinit failed

goroutine 1 [running, locked to thread]:
runtime.throw({0x3b7f18?, 0xaf350?})
        /home/walker/.bin/go/src/runtime/panic.go:1077 +0x44 fp=0x3f90072ba8 sp=0x3f90072b80 pc=0x463a4runtime.netpollinit()
        /home/walker/.bin/go/src/runtime/netpoll_epoll.go:28 +0x1b4 fp=0x3f90072c18 sp=0x3f90072ba8 pc=0x425b4
runtime.netpollGenericInit()
        /home/walker/.bin/go/src/runtime/netpoll.go:216 +0x64 fp=0x3f90072c28 sp=0x3f90072c18 pc=0x41a8c
internal/poll.runtime_pollServerInit()
        /home/walker/.bin/go/src/runtime/netpoll.go:208 +0x20 fp=0x3f90072c30 sp=0x3f90072c28 pc=0x72558
sync.(*Once).doSlow(0xc9d08?, 0xc9c4c?)
        /home/walker/.bin/go/src/sync/once.go:74 +0xf4 fp=0x3f90072c80 sp=0x3f90072c30 pc=0x8f024
sync.(*Once).Do(...)
        /home/walker/.bin/go/src/sync/once.go:65
internal/poll.(*pollDesc).init(0x3f900601a0, 0x3f90060180)
        /home/walker/.bin/go/src/internal/poll/fd_poll_runtime.go:39 +0x64 fp=0x3f90072c98 sp=0x3f90072c80 pc=0xc3d4c
internal/poll.(*FD).Init(0x3f90060180, {0x3acc3b?, 0x3f9000c0f0?}, 0xc?)
        /home/walker/.bin/go/src/internal/poll/fd_unix.go:65 +0xa0 fp=0x3f90072cb0 sp=0x3f90072c98 pc=0xc46a0
os.newFile(0x3, {0x3f9000c0f0, 0xc}, 0x1)
        /home/walker/.bin/go/src/os/file_unix.go:233 +0x1a0 fp=0x3f90072ce8 sp=0x3f90072cb0 pc=0xc9d68
os.openFileNolog({0x3f9000c0f0, 0xc}, 0x0, 0x0)
        /home/walker/.bin/go/src/os/file_unix.go:301 +0x1b0 fp=0x3f90072d28 sp=0x3f90072ce8 pc=0xc9f80
os.OpenFile({0x3f9000c0f0, 0xc}, 0x0, 0x0?)
        /home/walker/.bin/go/src/os/file.go:334 +0x64 fp=0x3f90072d58 sp=0x3f90072d28 pc=0xc902c
os.Open(...)
        /home/walker/.bin/go/src/os/file.go:314
google.golang.org/protobuf/internal/detrand.binaryHash()
        /home/walker/go/pkg/mod/google.golang.org/protobuf@v1.30.0/internal/detrand/rand.go:46 +0x48 fp=0x3f90072e18 sp=0x3f90072d58 pc=0x2c5d30
google.golang.org/protobuf/internal/detrand.init()
        /home/walker/go/pkg/mod/google.golang.org/protobuf@v1.30.0/internal/detrand/rand.go:38 +0x20 fp=0x3f90072e20 sp=0x3f90072e18 pc=0x2c5fd0
runtime.doInit1(0x661590)
        /home/walker/.bin/go/src/runtime/proc.go:6740 +0xdc fp=0x3f90072f48 sp=0x3f90072e20 pc=0x56a9c
runtime.doInit(...)
        /home/walker/.bin/go/src/runtime/proc.go:6707
runtime.main()
        /home/walker/.bin/go/src/runtime/proc.go:249 +0x3ac fp=0x3f90072fd8 sp=0x3f90072f48 pc=0x48d6c
runtime.goexit()
        /home/walker/.bin/go/src/runtime/asm_riscv64.s:512 +0x4 fp=0x3f90072fd8 sp=0x3f90072fd8 pc=0x7749c

goroutine 2 [force gc (idle)]:
runtime.gopark(0x0?, 0x0?, 0x0?, 0x0?, 0x0?)
        /home/walker/.bin/go/src/runtime/proc.go:398 +0x10c fp=0x3f9003efa8 sp=0x3f9003ef90 pc=0x49134
runtime.goparkunlock(...)
        /home/walker/.bin/go/src/runtime/proc.go:404
runtime.forcegchelper()
        /home/walker/.bin/go/src/runtime/proc.go:322 +0xd4 fp=0x3f9003efd8 sp=0x3f9003efa8 pc=0x48f9c
runtime.goexit()
        /home/walker/.bin/go/src/runtime/asm_riscv64.s:512 +0x4 fp=0x3f9003efd8 sp=0x3f9003efd8 pc=0x7749c
created by runtime.init.5 in goroutine 1
        /home/walker/.bin/go/src/runtime/proc.go:310 +0x28

goroutine 3 [GC sweep wait]:
runtime.gopark(0x0?, 0x0?, 0x0?, 0x0?, 0x0?)
        /home/walker/.bin/go/src/runtime/proc.go:398 +0x10c fp=0x3f9003f780 sp=0x3f9003f768 pc=0x49134
runtime.goparkunlock(...)
        /home/walker/.bin/go/src/runtime/proc.go:404
runtime.bgsweep(0x0?)
        /home/walker/.bin/go/src/runtime/mgcsweep.go:280 +0xb4 fp=0x3f9003f7c8 sp=0x3f9003f780 pc=0x34b94
runtime.gcenable.func1()
        /home/walker/.bin/go/src/runtime/mgc.go:200 +0x2c fp=0x3f9003f7d8 sp=0x3f9003f7c8 pc=0x292a4
runtime.goexit()
        /home/walker/.bin/go/src/runtime/asm_riscv64.s:512 +0x4 fp=0x3f9003f7d8 sp=0x3f9003f7d8 pc=0x7749c
created by runtime.gcenable in goroutine 1
        /home/walker/.bin/go/src/runtime/mgc.go:200 +0x70

goroutine 4 [GC scavenge wait]:
runtime.gopark(0x3f9005c000?, 0x43a150?, 0x0?, 0x0?, 0x3f90000d00?)
        /home/walker/.bin/go/src/runtime/proc.go:398 +0x10c fp=0x3f9003ff80 sp=0x3f9003ff68 pc=0x49134
runtime.goparkunlock(...)
        /home/walker/.bin/go/src/runtime/proc.go:404
runtime.(*scavengerState).park(0x6b1260)
        /home/walker/.bin/go/src/runtime/mgcscavenge.go:425 +0x68 fp=0x3f9003ffa8 sp=0x3f9003ff80 pc=0x322b8
runtime.bgscavenge(0x0?)
        /home/walker/.bin/go/src/runtime/mgcscavenge.go:653 +0x50 fp=0x3f9003ffc8 sp=0x3f9003ffa8 pc=0x32830
runtime.gcenable.func2()
        /home/walker/.bin/go/src/runtime/mgc.go:201 +0x2c fp=0x3f9003ffd8 sp=0x3f9003ffc8 pc=0x29244
runtime.goexit()
        /home/walker/.bin/go/src/runtime/asm_riscv64.s:512 +0x4 fp=0x3f9003ffd8 sp=0x3f9003ffd8 pc=0x7749c
created by runtime.gcenable in goroutine 1
        /home/walker/.bin/go/src/runtime/mgc.go:201 +0xb0

goroutine 5 [finalizer wait]:
runtime.gopark(0x73740?, 0x0?, 0x0?, 0x0?, 0x0?)
        /home/walker/.bin/go/src/runtime/proc.go:398 +0x10c fp=0x3f9003e5a8 sp=0x3f9003e590 pc=0x49134
runtime.runfinq()
        /home/walker/.bin/go/src/runtime/mfinal.go:193 +0x108 fp=0x3f9003e7d8 sp=0x3f9003e5a8 pc=0x28398
runtime.goexit()
        /home/walker/.bin/go/src/runtime/asm_riscv64.s:512 +0x4 fp=0x3f9003e7d8 sp=0x3f9003e7d8 pc=0x7749c
created by runtime.createfing in goroutine 1
        /home/walker/.bin/go/src/runtime/mfinal.go:163 +0x64

III. Compiling the Go Environment on a riscv64 Architecture

Since the VF2 development board is based on the riscv64 architecture, you don’t need to add the GOARCH environment configuration:

CGO_ENABLED=0 go build -ldflags="-s -w" -o helloRG hello.go

Then, upload it to the development board and run it:

[root@milkv]~# ./helloRG
Hello world

It runs perfectly fine.

It’s a bit strange to note that when you cross-compile Go programs on an x86 platform (such as “hello world” and a web-based LED program) and run them on an ARM platform, they work fine. However, they don’t run on the riscv64 platform.

i have a message error
fatal error: out of memory allocating heap arena map

runtime stack:
runtime.throw({0xac517?, 0x4000000?})
/usr/lib/go-1.19/src/runtime/panic.go:1047 +0x44 fp=0x3fffb2d730 sp=0x3fffb2d708 pc=0x4081c
runtime.(*mheap).sysAlloc(0x15e840, 0x0?)

i have the solution by myself
for Go you needs to enable the swap partition