Skip to content

Instantly share code, notes, and snippets.

@sithumonline
Created May 13, 2025 12:16
Show Gist options
  • Select an option

  • Save sithumonline/9355e8fad5051ed2d438ca1b56860940 to your computer and use it in GitHub Desktop.

Select an option

Save sithumonline/9355e8fad5051ed2d438ca1b56860940 to your computer and use it in GitHub Desktop.
Value va Pointer v1
package main
import (
"fmt"
"sync"
)
// Counter holds a simple integer.
type Counter struct {
N int
}
// IncValue is a VALUE receiver: it works on a COPY.
func (c Counter) IncValue() {
c.N++
fmt.Println(" [inside IncValue] c.N =", c.N)
}
// IncPtr is a POINTER receiver: it mutates the original.
func (c *Counter) IncPtr() {
c.N++
fmt.Println(" [inside IncPtr] c.N =", c.N)
}
/***********/
type SafeMap struct {
mu sync.Mutex
m map[int]int
}
// LockMap and UnlockMap use VALUE receivers — they lock/unlock a COPY of mu!
func (sm *SafeMap) LockMap() {
sm.mu.Lock()
}
func (sm *SafeMap) UnlockMap() {
sm.mu.Unlock()
}
// Store wraps a map write in those (ineffective) locks
func (sm SafeMap) Store(key, value int) {
sm.LockMap()
sm.m[key] = value
sm.UnlockMap()
}
/***********/
// S has one value‐receiver and one pointer‐receiver method.
type S struct{ V int }
// Value receiver: belongs to both S and *S.
func (s S) Val() {
fmt.Println("Called Val(), V =", s.V)
}
// Pointer receiver: belongs only to *S.
func (s *S) Ptr() {
fmt.Println("Called Ptr(), V =", s.V)
}
// Interfaces for each method.
type IVal interface{ Val() }
type IPtr interface{ Ptr() }
func main() {
fmt.Println("== Working with value instance ==")
c := Counter{N: 0}
fmt.Println("Start: c.N =", c.N)
// 1) Call the value-receiver method
c.IncValue()
fmt.Println("After IncValue(): c.N =", c.N)
// 2) Call the pointer-receiver method
c.IncPtr()
fmt.Println("After IncPtr(): c.N =", c.N)
/***********/
fmt.Println("\n== Working with pointer instance ==")
sm := SafeMap{m: make(map[int]int)}
var wg sync.WaitGroup
// crank up the concurrency
for i := 0; i < 10; i++ { // change to 10_000 for a real test; it'll be panic due to deadlock
wg.Add(1)
go func(i int) {
defer wg.Done()
sm.Store(i, i)
fmt.Println("storing", i)
}(i)
}
wg.Wait()
fmt.Println("finished storing", len(sm.m), "entries")
/***********/
fmt.Println("\n== Working with value and pointer receivers ==")
s := S{V: 42}
ps := &s
// IVal can be satisfied by S _or_ *S:
var iv1 IVal = s
iv1.Val() // OK: prints "Called Val(), V = 42"
var iv2 IVal = ps
iv2.Val() // OK: also prints "Called Val(), V = 42"
// IPtr can only be satisfied by *S:
var ip IPtr = ps
ip.Ptr() // OK: prints "Called Ptr(), V = 42"
// Uncommenting the next line causes a compile‐time error:
//var ip2 IPtr = s
//ip2.Ptr() // ERROR: cannot use s (type S) as type IPtr in assignment:
// → cannot use s (type S) as type IPtr in assignment:
// S does not implement IPtr (Ptr method has pointer receiver)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment