reorganize: consolidate demo directories
- Consolidate _demo, _pydemo, _embdemo into single _demo directory structure
- Organize demos by language: _demo/{go,py,c,embed}/
- Categorize demos based on imports:
- Python library demos (py imports) → _demo/py/
- C/C++ library demos (c/cpp imports) → _demo/c/
- Go-specific demos → _demo/go/
- Embedded demos → _demo/embed/
- Move C-related demos (asm*, cabi*, cgo*, linkname, targetsbuild) from go/ to c/
- Update all path references in README.md and GitHub workflows
- Improve demo organization and navigation as requested in #1256
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
31
_demo/go/async/async/async.go
Normal file
31
_demo/go/async/async/async.go
Normal file
@@ -0,0 +1,31 @@
|
||||
package async
|
||||
|
||||
import (
|
||||
_ "unsafe"
|
||||
)
|
||||
|
||||
type Void = [0]byte
|
||||
|
||||
type Future[T any] interface {
|
||||
Then(cb func(T))
|
||||
}
|
||||
|
||||
type future[T any] struct {
|
||||
cb func(func(T))
|
||||
}
|
||||
|
||||
func (f *future[T]) Then(cb func(T)) {
|
||||
f.cb(cb)
|
||||
}
|
||||
|
||||
func Async[T any](fn func(func(T))) Future[T] {
|
||||
return &future[T]{fn}
|
||||
}
|
||||
|
||||
func Run[T any](future Future[T]) T {
|
||||
var ret T
|
||||
future.Then(func(v T) {
|
||||
ret = v
|
||||
})
|
||||
return ret
|
||||
}
|
||||
23
_demo/go/async/main.go
Normal file
23
_demo/go/async/main.go
Normal file
@@ -0,0 +1,23 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/goplus/llgo/_demo/go/async/async"
|
||||
"github.com/goplus/llgo/_demo/go/async/timeout"
|
||||
)
|
||||
|
||||
func Sleep(i int, d time.Duration) async.Future[int] {
|
||||
return async.Async(func(resolve func(int)) {
|
||||
timeout.Timeout(d).Then(func(async.Void) {
|
||||
resolve(i)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
func main() {
|
||||
async.Run(async.Async(func(resolve func(async.Void)) {
|
||||
println("read file")
|
||||
defer resolve(async.Void{})
|
||||
}))
|
||||
}
|
||||
16
_demo/go/async/timeout/timeout.go
Normal file
16
_demo/go/async/timeout/timeout.go
Normal file
@@ -0,0 +1,16 @@
|
||||
package timeout
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/goplus/llgo/_demo/go/async/async"
|
||||
)
|
||||
|
||||
func Timeout(d time.Duration) async.Future[async.Void] {
|
||||
return async.Async(func(resolve func(async.Void)) {
|
||||
go func() {
|
||||
time.Sleep(d)
|
||||
resolve(async.Void{})
|
||||
}()
|
||||
})
|
||||
}
|
||||
28
_demo/go/checkfile/demo.go
Normal file
28
_demo/go/checkfile/demo.go
Normal file
@@ -0,0 +1,28 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
)
|
||||
|
||||
func main() {
|
||||
tempDir := os.TempDir()
|
||||
noexist := filepath.Join(tempDir, "noexist.txt")
|
||||
|
||||
if _, err := os.Stat(noexist); err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
fmt.Println("noexist:", err.Error())
|
||||
} else {
|
||||
fmt.Println("exist,other err:", err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
if _, err := os.Open(noexist); err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
fmt.Println("noexist:", err.Error())
|
||||
} else {
|
||||
fmt.Println("exist,other err:", err.Error())
|
||||
}
|
||||
}
|
||||
}
|
||||
20
_demo/go/commandrun/commandrun.go
Normal file
20
_demo/go/commandrun/commandrun.go
Normal file
@@ -0,0 +1,20 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
)
|
||||
|
||||
func main() {
|
||||
var data bytes.Buffer
|
||||
cmd := exec.Command("echo", "hello llgo")
|
||||
cmd.Dir = filepath.Dir("./")
|
||||
cmd.Stdout = &data
|
||||
err := cmd.Run()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
println("len:", len(data.Bytes()))
|
||||
println("data:", data.String())
|
||||
}
|
||||
9
_demo/go/complex/cmplx.go
Normal file
9
_demo/go/complex/cmplx.go
Normal file
@@ -0,0 +1,9 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"math/cmplx"
|
||||
)
|
||||
|
||||
func main() {
|
||||
println("abs(3+4i):", cmplx.Abs(3+4i))
|
||||
}
|
||||
18
_demo/go/defer/main.go
Normal file
18
_demo/go/defer/main.go
Normal file
@@ -0,0 +1,18 @@
|
||||
package main
|
||||
|
||||
func main() {
|
||||
var a int = 5
|
||||
defer println(a)
|
||||
defer func() {
|
||||
println(a)
|
||||
}()
|
||||
defer func() {
|
||||
println(recover().(string))
|
||||
}()
|
||||
a = 10
|
||||
panic("error")
|
||||
//Output:
|
||||
// error
|
||||
// 10
|
||||
// 5
|
||||
}
|
||||
42
_demo/go/failed/stacktrace/main.go
Normal file
42
_demo/go/failed/stacktrace/main.go
Normal file
@@ -0,0 +1,42 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
type MyStruct[T any] struct {
|
||||
value T
|
||||
}
|
||||
|
||||
func (m *MyStruct[T]) Method() {
|
||||
fmt.Println("In generic method")
|
||||
genericFunc[T](m.value)
|
||||
}
|
||||
|
||||
func genericFunc[T any](v T) {
|
||||
fmt.Println("In generic function")
|
||||
normalFunc()
|
||||
}
|
||||
|
||||
func normalFunc() {
|
||||
fmt.Println("In normal function")
|
||||
panic("panic occurs here")
|
||||
}
|
||||
|
||||
func main() {
|
||||
m := &MyStruct[string]{value: "hello"}
|
||||
m.Method()
|
||||
}
|
||||
|
||||
//Expected:
|
||||
// In generic method
|
||||
// In generic function
|
||||
// In normal function
|
||||
// panic: panic occurs here
|
||||
|
||||
// [0x00C6D310 github.com/goplus/llgo/internal/runtime.Rethrow+0x2f, SP = 0x60]
|
||||
// [0x00C6CF44 github.com/goplus/llgo/internal/runtime.Panic+0x2d, SP = 0x50]
|
||||
// [0x00C69420 main.normalFunc+0xf, SP = 0xa8]
|
||||
// [0x00C69564 main.genericFunc[string]+0x18, SP = 0x74]
|
||||
// [0x00C694A8 main.(*MyStruct[string]).Method+0x1f, SP = 0x84]
|
||||
// [0x00C6936C main+0x4, SP = 0x40]
|
||||
3
_demo/go/go.mod
Normal file
3
_demo/go/go.mod
Normal file
@@ -0,0 +1,3 @@
|
||||
module github.com/goplus/llgo/_demo/go
|
||||
|
||||
go 1.20
|
||||
0
_demo/go/go.sum
Normal file
0
_demo/go/go.sum
Normal file
12
_demo/go/goroutine/goroutine.go
Normal file
12
_demo/go/goroutine/goroutine.go
Normal file
@@ -0,0 +1,12 @@
|
||||
package main
|
||||
|
||||
func main() {
|
||||
done := false
|
||||
go func() {
|
||||
println("Hello, goroutine")
|
||||
done = true
|
||||
}()
|
||||
for !done {
|
||||
print(".")
|
||||
}
|
||||
}
|
||||
7
_demo/go/gotime/time.go
Normal file
7
_demo/go/gotime/time.go
Normal file
@@ -0,0 +1,7 @@
|
||||
package main
|
||||
|
||||
import "time"
|
||||
|
||||
func main() {
|
||||
println(time.Now().String())
|
||||
}
|
||||
85
_demo/go/ifaceconv/main.go
Normal file
85
_demo/go/ifaceconv/main.go
Normal file
@@ -0,0 +1,85 @@
|
||||
package main
|
||||
|
||||
// Tests of interface conversions and type assertions.
|
||||
|
||||
type I0 interface {
|
||||
}
|
||||
type I1 interface {
|
||||
f()
|
||||
}
|
||||
type I2 interface {
|
||||
f()
|
||||
g()
|
||||
}
|
||||
|
||||
type C0 struct{}
|
||||
type C1 struct{}
|
||||
|
||||
func (C1) f() {}
|
||||
|
||||
type C2 struct{}
|
||||
|
||||
func (C2) f() {}
|
||||
func (C2) g() {}
|
||||
|
||||
func main() {
|
||||
var i0 I0
|
||||
var i1 I1
|
||||
var i2 I2
|
||||
|
||||
// Nil always causes a type assertion to fail, even to the
|
||||
// same type.
|
||||
if _, ok := i0.(I0); ok {
|
||||
panic("nil i0.(I0) succeeded")
|
||||
}
|
||||
if _, ok := i1.(I1); ok {
|
||||
panic("nil i1.(I1) succeeded")
|
||||
}
|
||||
if _, ok := i2.(I2); ok {
|
||||
panic("nil i2.(I2) succeeded")
|
||||
}
|
||||
|
||||
// Conversions can't fail, even with nil.
|
||||
_ = I0(i0)
|
||||
|
||||
_ = I0(i1)
|
||||
_ = I1(i1)
|
||||
|
||||
_ = I0(i2)
|
||||
_ = I1(i2)
|
||||
_ = I2(i2)
|
||||
|
||||
// Non-nil type assertions pass or fail based on the concrete type.
|
||||
i1 = C1{}
|
||||
if _, ok := i1.(I0); !ok {
|
||||
panic("C1 i1.(I0) failed")
|
||||
}
|
||||
if _, ok := i1.(I1); !ok {
|
||||
panic("C1 i1.(I1) failed")
|
||||
}
|
||||
if _, ok := i1.(I2); ok {
|
||||
panic("C1 i1.(I2) succeeded")
|
||||
}
|
||||
|
||||
i1 = C2{}
|
||||
if _, ok := i1.(I0); !ok {
|
||||
panic("C2 i1.(I0) failed")
|
||||
}
|
||||
if _, ok := i1.(I1); !ok {
|
||||
panic("C2 i1.(I1) failed")
|
||||
}
|
||||
if _, ok := i1.(I2); !ok {
|
||||
panic("C2 i1.(I2) failed")
|
||||
}
|
||||
|
||||
// Conversions can't fail.
|
||||
i1 = C1{}
|
||||
if I0(i1) == nil {
|
||||
panic("C1 I0(i1) was nil")
|
||||
}
|
||||
if I1(i1) == nil {
|
||||
panic("C1 I1(i1) was nil")
|
||||
}
|
||||
|
||||
println("pass")
|
||||
}
|
||||
9
_demo/go/logdemo/log.go
Normal file
9
_demo/go/logdemo/log.go
Normal file
@@ -0,0 +1,9 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"log"
|
||||
)
|
||||
|
||||
func main() {
|
||||
log.Println("Hello")
|
||||
}
|
||||
11
_demo/go/math/math.go
Normal file
11
_demo/go/math/math.go
Normal file
@@ -0,0 +1,11 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"math"
|
||||
)
|
||||
|
||||
func main() {
|
||||
println(math.Sqrt(2))
|
||||
println(math.Abs(-1.2))
|
||||
println(math.Ldexp(1.2, 3))
|
||||
}
|
||||
13
_demo/go/mimeheader/mimeheader.go
Normal file
13
_demo/go/mimeheader/mimeheader.go
Normal file
@@ -0,0 +1,13 @@
|
||||
package main
|
||||
|
||||
import "net/textproto"
|
||||
|
||||
func main() {
|
||||
h := make(textproto.MIMEHeader)
|
||||
h.Set("host", "www.example.com")
|
||||
println(h.Get("Host"))
|
||||
}
|
||||
|
||||
/* Expected output:
|
||||
www.example.com
|
||||
*/
|
||||
34
_demo/go/mkdirdemo/mkdir.go
Normal file
34
_demo/go/mkdirdemo/mkdir.go
Normal file
@@ -0,0 +1,34 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
)
|
||||
|
||||
func main() {
|
||||
tempDir, err := os.MkdirTemp("", "example*")
|
||||
if err != nil {
|
||||
fmt.Println("Failed to create temp directory:", err)
|
||||
return
|
||||
}
|
||||
defer os.Remove(tempDir)
|
||||
fmt.Println("Temp directory:", tempDir)
|
||||
|
||||
tempFile, err := os.CreateTemp("", "example*.txt")
|
||||
if err != nil {
|
||||
fmt.Println("Failed to create temp file:", err)
|
||||
return
|
||||
}
|
||||
defer tempFile.Close()
|
||||
defer os.Remove(tempFile.Name())
|
||||
fmt.Println("Temp file:", tempFile.Name())
|
||||
|
||||
nestedDir := filepath.Join("nested", "directory")
|
||||
err = os.MkdirAll(nestedDir, 0755)
|
||||
if err != nil {
|
||||
fmt.Println("Failed to create nested directory:", err)
|
||||
return
|
||||
}
|
||||
fmt.Println("Nest directory:", nestedDir)
|
||||
}
|
||||
19
_demo/go/oslookpath/lookpath.go
Normal file
19
_demo/go/oslookpath/lookpath.go
Normal file
@@ -0,0 +1,19 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os/exec"
|
||||
"runtime"
|
||||
)
|
||||
|
||||
func main() {
|
||||
ls := "ls"
|
||||
if runtime.GOOS == "windows" {
|
||||
ls = "dir"
|
||||
}
|
||||
lspath, _ := exec.LookPath(ls)
|
||||
if lspath != "" {
|
||||
ls = lspath
|
||||
}
|
||||
fmt.Println(ls)
|
||||
}
|
||||
18
_demo/go/randcrypt/rand.go
Normal file
18
_demo/go/randcrypt/rand.go
Normal file
@@ -0,0 +1,18 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
func main() {
|
||||
c := 10
|
||||
b := make([]byte, c)
|
||||
_, err := rand.Read(b)
|
||||
if err != nil {
|
||||
fmt.Println("error:", err)
|
||||
return
|
||||
}
|
||||
// The slice should now contain random bytes instead of only zeroes.
|
||||
fmt.Printf("%x\n", b)
|
||||
}
|
||||
12
_demo/go/randdemo/rand.go
Normal file
12
_demo/go/randdemo/rand.go
Normal file
@@ -0,0 +1,12 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math/rand"
|
||||
)
|
||||
|
||||
func main() {
|
||||
fmt.Println(rand.Intn(100))
|
||||
fmt.Println(rand.Intn(100))
|
||||
fmt.Println(rand.Intn(100))
|
||||
}
|
||||
29
_demo/go/readdir/main.go
Normal file
29
_demo/go/readdir/main.go
Normal file
@@ -0,0 +1,29 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
)
|
||||
|
||||
func main() {
|
||||
entries, err := os.ReadDir("../")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
if len(entries) == 0 {
|
||||
panic("No files found")
|
||||
}
|
||||
var check int
|
||||
for _, e := range entries {
|
||||
fmt.Printf("%s isDir[%t]\n", e.Name(), e.IsDir())
|
||||
if !e.IsDir() {
|
||||
switch e.Name() {
|
||||
case "go.sum", "go.mod":
|
||||
check++
|
||||
}
|
||||
}
|
||||
}
|
||||
if check != 2 {
|
||||
panic("Bad readdir entries go.mod/go.sum")
|
||||
}
|
||||
}
|
||||
42
_demo/go/reflectfunc/reflectfunc.go
Normal file
42
_demo/go/reflectfunc/reflectfunc.go
Normal file
@@ -0,0 +1,42 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
)
|
||||
|
||||
func add(a, b int) int {
|
||||
return a + b
|
||||
}
|
||||
|
||||
func main() {
|
||||
fn := func(a, b int) int {
|
||||
return a + b
|
||||
}
|
||||
var i int
|
||||
fn1 := func() {
|
||||
i++
|
||||
}
|
||||
fn2 := func() func() {
|
||||
return func() {
|
||||
println("closure", i)
|
||||
}
|
||||
}
|
||||
|
||||
fns := []any{add, fn, fn1, fn2}
|
||||
for _, fn := range fns {
|
||||
v := reflect.ValueOf(fn)
|
||||
fmt.Println(v.Type())
|
||||
fmt.Println(v.Kind())
|
||||
if v.Kind() != reflect.Func {
|
||||
panic(fmt.Sprintf("not func: %T", fn))
|
||||
}
|
||||
|
||||
t := v.Type()
|
||||
fmt.Println(t)
|
||||
fmt.Println(t.Kind())
|
||||
if t.Kind() != reflect.Func {
|
||||
panic(fmt.Sprintf("not func: %T", fn))
|
||||
}
|
||||
}
|
||||
}
|
||||
112
_demo/go/sync/sync.go
Normal file
112
_demo/go/sync/sync.go
Normal file
@@ -0,0 +1,112 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
)
|
||||
|
||||
// Counter represents a thread-safe counter
|
||||
type Counter struct {
|
||||
mu sync.Mutex
|
||||
value int64
|
||||
}
|
||||
|
||||
// Increment increases the counter value by 1
|
||||
func (c *Counter) Increment() {
|
||||
c.mu.Lock()
|
||||
defer c.mu.Unlock()
|
||||
c.value++
|
||||
}
|
||||
|
||||
// GetValue returns the current value of the counter
|
||||
func (c *Counter) GetValue() int64 {
|
||||
c.mu.Lock()
|
||||
defer c.mu.Unlock()
|
||||
return c.value
|
||||
}
|
||||
|
||||
// Constant values for the test
|
||||
const (
|
||||
numGoroutines = 64
|
||||
numIterations = 10000
|
||||
expectedTotal = numGoroutines * numIterations
|
||||
)
|
||||
|
||||
func main() {
|
||||
// Create a new counter instance
|
||||
counter := &Counter{}
|
||||
|
||||
// Create a wait group to wait for all goroutines to finish
|
||||
var wg sync.WaitGroup
|
||||
|
||||
// Track active goroutines for monitoring
|
||||
var activeGoroutines int32
|
||||
|
||||
// Start time
|
||||
startTime := time.Now()
|
||||
|
||||
// Launch goroutines
|
||||
for i := 0; i < numGoroutines; i++ {
|
||||
wg.Add(1)
|
||||
atomic.AddInt32(&activeGoroutines, 1)
|
||||
|
||||
go func(id int) {
|
||||
defer func() {
|
||||
wg.Done()
|
||||
atomic.AddInt32(&activeGoroutines, -1)
|
||||
}()
|
||||
|
||||
// Each goroutine increments the counter numIterations times
|
||||
for j := 0; j < numIterations; j++ {
|
||||
counter.Increment()
|
||||
|
||||
// Simulate varying workload with random sleeps
|
||||
if j%100 == 0 {
|
||||
time.Sleep(time.Microsecond)
|
||||
}
|
||||
}
|
||||
fmt.Printf("Goroutine %d finished\n", id)
|
||||
}(i)
|
||||
}
|
||||
|
||||
// Monitor progress in a separate goroutine
|
||||
go func() {
|
||||
for {
|
||||
active := atomic.LoadInt32(&activeGoroutines)
|
||||
if active == 0 {
|
||||
break
|
||||
}
|
||||
fmt.Printf("Active goroutines: %d\n", active)
|
||||
time.Sleep(time.Second)
|
||||
}
|
||||
}()
|
||||
|
||||
// Wait for all goroutines to complete
|
||||
wg.Wait()
|
||||
|
||||
// Calculate execution time
|
||||
duration := time.Since(startTime)
|
||||
|
||||
// Get and verify the final result
|
||||
finalValue := counter.GetValue()
|
||||
fmt.Printf("\nExecution completed in: %v\n", duration)
|
||||
fmt.Printf("Final counter value: %d\n", finalValue)
|
||||
fmt.Printf("Expected value: %d\n", expectedTotal)
|
||||
|
||||
// Assert the result
|
||||
if finalValue != expectedTotal {
|
||||
panic(fmt.Sprintf("ERROR: Counter value mismatch! Expected %d, got %d\n",
|
||||
expectedTotal, finalValue))
|
||||
} else {
|
||||
fmt.Printf("SUCCESS: Counter value matches expected total\n")
|
||||
}
|
||||
|
||||
// Print some statistics
|
||||
opsPerSecond := float64(expectedTotal) / duration.Seconds()
|
||||
fmt.Printf("\nStatistics:\n")
|
||||
fmt.Printf("Operations per second: %.2f\n", opsPerSecond)
|
||||
fmt.Printf("Average time per operation: %.2f ns\n",
|
||||
float64(duration.Nanoseconds())/float64(expectedTotal))
|
||||
}
|
||||
26
_demo/go/sysexec/exec.go
Normal file
26
_demo/go/sysexec/exec.go
Normal file
@@ -0,0 +1,26 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os/exec"
|
||||
"runtime"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
func main() {
|
||||
ls := "ls"
|
||||
args := []string{ls, "-l"}
|
||||
if runtime.GOOS == "windows" {
|
||||
ls = "dir"
|
||||
args = []string{ls}
|
||||
}
|
||||
lspath, _ := exec.LookPath(ls)
|
||||
if lspath != "" {
|
||||
ls = lspath
|
||||
}
|
||||
err := syscall.Exec(ls, args, nil)
|
||||
if err != nil {
|
||||
fmt.Println("syscall.Exec error:", err)
|
||||
return
|
||||
}
|
||||
}
|
||||
11
_demo/go/timedur/timedur.go
Normal file
11
_demo/go/timedur/timedur.go
Normal file
@@ -0,0 +1,11 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
)
|
||||
|
||||
func main() {
|
||||
t := time.Now().Add(time.Second * 5)
|
||||
fmt.Println(time.Until(t))
|
||||
}
|
||||
Reference in New Issue
Block a user