On my adventures in playing with RISC-V (see Emulating RISC-V, and IPFS on RISC-V), I hit on a few issues.
I was struggling to find a guide online on how to cross compile Go code on RISC-V, when cgo is involved. Here is a quick guide and trouble shooting tips to help others.

Important: the riscv64 architecture was not added until Go version 1.15.x, you will need to make sure you are running a recent release.
Here is the Github issue that tracked the implementation https://github.com/golang/go/issues/36641

Setting up and compiling

# Install standard GCC for your system
sudo apt install build-essential
# Add the RISC-V GCC package
sudo apt install g++-riscv64-linux-gnu gcc-riscv64-linux-gnu

# Tell golang what the compilation target is
# Importantly, set the CC (Cross Compiler) to use the riscv64 version of GCC, instead of our system's default
export GOOS=linux
export GOARCH=riscv64
export CGO_ENABLED=1
export CC=riscv64-linux-gnu-gcc

Now files will compile when cross compiling for RISC-V

# Code sample from issue https://github.com/golang/go/issues/36641#issuecomment-630204733
# Create a sample app
cat > cgo.go << EOF
package main

import "runtime"

/*
#include <stdio.h>

void hello(char *goos, char *goarch) {
        printf("Hi from cgo on %s/%s!\n", goos, goarch);
}
*/
import "C"

func main() {
        goos := C.CString(runtime.GOOS)
        goarch := C.CString(runtime.GOARCH)
        C.hello(goos, goarch)
}
EOF

# build it
go build ./cgo.go

Troubleshooting

Verify environment settings

When you run go env you should see this similar output.

$ go env
GOOS="linux"
GOARCH="riscv64"
CGO_ENABLED="1"
CC="riscv64-linux-gnu-gcc"
...

Force env settings for a single go build

You can preface the go command with the environment settings you want, if you cannot export

env GOOS=linux GOARCH=riscv64 CGO_ENABLED=1 CC=riscv64-linux-gnu-gcc go build

Older version of Go

If you see something similar to this, then you have an older version of golang.
Solution: Install a version later than 1.15.x

$ go build ./cgo.go
/usr/bin/ld: $WORK/b009/_x008.o: in function `x_cgo_thread_start':
/usr/lib/go-1.15/src/runtime/cgo/gcc_util.c:23: undefined reference to `_cgo_sys_thread_start'
collect2: error: ld returned 1 exit status

Cross compiler not set

This is what got me stuck for quite a while. This happens when CC is still set to your system default gcc.
Solution: set export CC=riscv64-linux-gnu-gcc

$ go build ./cgo.go
gcc_riscv64.S: Assembler messages:
gcc_riscv64.S:15: Error: no such instruction: `sd x1,-200(sp)'
gcc_riscv64.S:16: Error: no such instruction: `addi sp,sp,-200'
gcc_riscv64.S:17: Error: no such instruction: `sd x8,8(sp)'
gcc_riscv64.S:18: Error: no such instruction: `sd x9,16(sp)'
gcc_riscv64.S:19: Error: no such instruction: `sd x18,24(sp)'
...
gcc_riscv64.S:29: Error: no such instruction: `fsd f8,104(sp)'
gcc_riscv64.S:30: Error: no such instruction: `fsd f9,112(sp)'
gcc_riscv64.S:31: Error: no such instruction: `fsd f18,120(sp)'
...
gcc_riscv64.S:43: Error: no such instruction: `mv s1,a0'
gcc_riscv64.S:44: Error: no such instruction: `mv s0,a1'
gcc_riscv64.S:45: Error: no such instruction: `mv a0,a2'
gcc_riscv64.S:46: Error: no such instruction: `jalr ra,s0'
gcc_riscv64.S:47: Error: no such instruction: `jalr ra,s1'
gcc_riscv64.S:49: Error: no such instruction: `ld x1,0(sp)'
gcc_riscv64.S:50: Error: no such instruction: `ld x8,8(sp)'
...
gcc_riscv64.S:62: Error: too many memory references for `fld'
gcc_riscv64.S:63: Error: too many memory references for `fld'
gcc_riscv64.S:64: Error: too many memory references for `fld'
...
gcc_riscv64.S:74: Error: no such instruction: `addi sp,sp,200'
gcc_riscv64.S:76: Error: no such instruction: `jr ra'