Repository: zimmski/go-leak
Branch: master
Commit: a11b0b936d24
Files: 8
Total size: 6.1 KB
Directory structure:
gitextract_e3lwpy1i/
├── .gitignore
├── LICENSE
├── README.md
├── goroutine.go
├── goroutine_test.go
├── init.go
├── memory.go
└── memory_test.go
================================================
FILE CONTENTS
================================================
================================================
FILE: .gitignore
================================================
# Compiled Object files, Static and Dynamic libs (Shared Objects)
*.o
*.a
*.so
# Folders
_obj
_test
# Architecture specific extensions/prefixes
*.[568vq]
[568vq].out
*.cgo1.go
*.cgo2.c
_cgo_defun.c
_cgo_gotypes.go
_cgo_export.*
_testmain.go
*.exe
*.test
*.prof
================================================
FILE: LICENSE
================================================
The MIT License (MIT)
Copyright (c) 2014 Markus Zimmermann
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
================================================
FILE: README.md
================================================
# go-leak [](https://godoc.org/github.com/zimmski/go-leak)
The std packages of Go do currently not included detection for leaks. go-leak is a package which should help you find leaks in your code. If you have any ideas on how to improve this package or have problems of any kind with it, please [submit an issue](https://github.com/zimmski/go-leak/issues/new) through the [issue tracker](https://github.com/zimmski/go-leak/issues).
> **Note:** This package does not work anymore. It worked for some use-cases I had with an older Go version but with >= 1.4 it does not work at all. I have it on my TODO to redo the whole thing and add some more use-cases but there are some other open source projects I have to do first. So if you have some time on your hand and would like to contribute mail me or submit an issue in the project's tracker.
> **Note:** Since Go is scoped it is important to avoid new variables that are in the same scope as the mark-and-release calls.
## goroutines
If you want to know if a function is leaking goroutines:
```go
leaks := leak.GoRoutineLeaks(foo)
if leaks > 0 {
panic("foo is leaking!")
}
```
If you want to know if a code is leaking goroutines:
```go
m := MarkGoRoutines()
// some code
leaks := m.Release()
if leaks > 0 {
panic("some code is leaking!")
}
```
## memory
If you want to know if a function is leaking memory:
```go
leaks := leak.MemoryLeaks(foo)
if leaks > 0 {
panic("foo is leaking!")
}
```
If you want to know if a code is leaking memory:
```go
m := MarkMemory()
// some code
leaks := m.Release()
if leaks > 0 {
panic("some code is leaking!")
}
```
================================================
FILE: goroutine.go
================================================
package leak
import (
"runtime"
)
func GoRoutineLeaks(f func()) int {
then := runtime.NumGoroutine()
f()
now := runtime.NumGoroutine()
return now - then
}
type GoRoutineMark struct {
then int
now int
}
func MarkGoRoutines() *GoRoutineMark {
m := &GoRoutineMark{}
m.then = runtime.NumGoroutine()
return m
}
func (m *GoRoutineMark) Release() int {
m.now = runtime.NumGoroutine()
return m.now - m.then
}
================================================
FILE: goroutine_test.go
================================================
package leak
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestGoRoutineLeaks(t *testing.T) {
leaks := GoRoutineLeaks(func() {
c := make(chan bool)
leaks := GoRoutineLeaks(func() {
go func() {
<-c
}()
})
assert.Equal(t, 1, leaks)
c <- true
})
assert.Equal(t, 0, leaks)
}
func TestGoRoutineMark(t *testing.T) {
c := make(chan bool)
m := MarkGoRoutines()
go func() {
<-c
}()
assert.Equal(t, 1, m.Release())
c <- true
assert.Equal(t, 0, m.Release())
}
================================================
FILE: init.go
================================================
package leak
import (
"sync"
)
var fixRan = false
var fixMutex sync.Mutex
func init() {
// FIXME there is an allocation for the first started go routine, since I do not know where the allocation is coming from or how to fix that, I just want to ignore it by making an early goroutine. This does NOT show up during test execution. This is easily explained since AFAIK the tests are run in goroutines.
fixMutex.Lock()
defer fixMutex.Unlock()
if fixRan {
return
}
fixRan = true
ch := func() chan bool {
ch := make(chan bool)
go func() {
ch <- true
close(ch)
}()
return ch
}()
<-ch
}
================================================
FILE: memory.go
================================================
package leak
import (
"runtime"
)
func MemoryLeaks(f func()) int {
var then = new(runtime.MemStats)
var now = new(runtime.MemStats)
runtime.GC()
runtime.ReadMemStats(then)
f()
runtime.GC()
runtime.ReadMemStats(now)
return int((now.Mallocs - then.Mallocs) - (now.Frees - then.Frees))
}
type MemoryMark struct {
then *runtime.MemStats
now *runtime.MemStats
}
func MarkMemory() *MemoryMark {
m := &MemoryMark{
then: new(runtime.MemStats),
now: new(runtime.MemStats),
}
runtime.GC()
runtime.ReadMemStats(m.then)
return m
}
func (m *MemoryMark) Release() int {
runtime.GC()
runtime.ReadMemStats(m.now)
return int((m.now.Mallocs - m.then.Mallocs) - (m.now.Frees - m.then.Frees))
}
================================================
FILE: memory_test.go
================================================
package leak
import (
"testing"
"github.com/stretchr/testify/assert"
)
type MemoryLeaker struct {
Foo int
}
func TestMemoryLeaks(t *testing.T) {
leaks := MemoryLeaks(func() {
var leaking *MemoryLeaker
leaks := MemoryLeaks(func() {
leaking = &MemoryLeaker{
Foo: 123,
}
})
assert.Equal(t, 1, leaks)
leaking = nil
})
assert.Equal(t, 0, leaks)
}
func TestMemoryLeaksGoroutine(t *testing.T) {
leaks := MemoryLeaks(func() {
ch := func() chan bool {
ch := make(chan bool)
go func() {
ch <- true
close(ch)
}()
return ch
}()
<-ch
})
assert.Equal(t, 0, leaks)
}
var leaking *MemoryLeaker
func TestMemoryMark(t *testing.T) {
m := MarkMemory()
leaking = leakMemory()
assert.Equal(t, 1, m.Release())
leaking = nil
assert.Equal(t, 0, m.Release())
}
func leakMemory() *MemoryLeaker {
return &MemoryLeaker{
Foo: 123,
}
}
gitextract_e3lwpy1i/ ├── .gitignore ├── LICENSE ├── README.md ├── goroutine.go ├── goroutine_test.go ├── init.go ├── memory.go └── memory_test.go
SYMBOL INDEX (16 symbols across 5 files)
FILE: goroutine.go
function GoRoutineLeaks (line 7) | func GoRoutineLeaks(f func()) int {
type GoRoutineMark (line 17) | type GoRoutineMark struct
method Release (line 30) | func (m *GoRoutineMark) Release() int {
function MarkGoRoutines (line 22) | func MarkGoRoutines() *GoRoutineMark {
FILE: goroutine_test.go
function TestGoRoutineLeaks (line 9) | func TestGoRoutineLeaks(t *testing.T) {
function TestGoRoutineMark (line 27) | func TestGoRoutineMark(t *testing.T) {
FILE: init.go
function init (line 10) | func init() {
FILE: memory.go
function MemoryLeaks (line 7) | func MemoryLeaks(f func()) int {
type MemoryMark (line 22) | type MemoryMark struct
method Release (line 39) | func (m *MemoryMark) Release() int {
function MarkMemory (line 27) | func MarkMemory() *MemoryMark {
FILE: memory_test.go
type MemoryLeaker (line 9) | type MemoryLeaker struct
function TestMemoryLeaks (line 13) | func TestMemoryLeaks(t *testing.T) {
function TestMemoryLeaksGoroutine (line 31) | func TestMemoryLeaksGoroutine(t *testing.T) {
function TestMemoryMark (line 53) | func TestMemoryMark(t *testing.T) {
function leakMemory (line 65) | func leakMemory() *MemoryLeaker {
Condensed preview — 8 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (7K chars).
[
{
"path": ".gitignore",
"chars": 266,
"preview": "# Compiled Object files, Static and Dynamic libs (Shared Objects)\n*.o\n*.a\n*.so\n\n# Folders\n_obj\n_test\n\n# Architecture spe"
},
{
"path": "LICENSE",
"chars": 1085,
"preview": "The MIT License (MIT)\n\nCopyright (c) 2014 Markus Zimmermann\n\nPermission is hereby granted, free of charge, to any person"
},
{
"path": "README.md",
"chars": 1688,
"preview": "# go-leak [](https://godoc.org/github.com/zimmski/go-le"
},
{
"path": "goroutine.go",
"chars": 425,
"preview": "package leak\n\nimport (\n\t\"runtime\"\n)\n\nfunc GoRoutineLeaks(f func()) int {\n\tthen := runtime.NumGoroutine()\n\n\tf()\n\n\tnow := "
},
{
"path": "goroutine_test.go",
"chars": 513,
"preview": "package leak\n\nimport (\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/assert\"\n)\n\nfunc TestGoRoutineLeaks(t *testing.T) {\n\tlea"
},
{
"path": "init.go",
"chars": 617,
"preview": "package leak\n\nimport (\n\t\"sync\"\n)\n\nvar fixRan = false\nvar fixMutex sync.Mutex\n\nfunc init() {\n\t// FIXME there is an alloca"
},
{
"path": "memory.go",
"chars": 712,
"preview": "package leak\n\nimport (\n\t\"runtime\"\n)\n\nfunc MemoryLeaks(f func()) int {\n\tvar then = new(runtime.MemStats)\n\tvar now = new(r"
},
{
"path": "memory_test.go",
"chars": 890,
"preview": "package leak\n\nimport (\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/assert\"\n)\n\ntype MemoryLeaker struct {\n\tFoo int\n}\n\nfunc "
}
]
About this extraction
This page contains the full source code of the zimmski/go-leak GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 8 files (6.1 KB), approximately 1.8k tokens, and a symbol index with 16 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.