From 140827a0fe8407a1a8fae466e36aadcdcd77c47c Mon Sep 17 00:00:00 2001 From: Abhinav Gupta Date: Fri, 3 Mar 2023 07:48:22 -0800 Subject: [PATCH 1/3] interface-receiver: Clarify why value receiver can be called The guidance in this section was a bit confusing because it didn't quite explain why we could only call Read, not Write, on the values stored in the map. Resolves #163 --- CHANGELOG.md | 4 ++++ src/interface-receiver.md | 11 ++++++++--- style.md | 11 ++++++++--- 3 files changed, 20 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 508c4b92..d81ae73d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +# 2023-03-03 + +- Receivers and Interfaces: Clarify subtlety with pointer receivers and values. + # 2022-10-18 - Add guidance on managing goroutine lifecycles. diff --git a/src/interface-receiver.md b/src/interface-receiver.md index 6d4b485e..0d7e3733 100644 --- a/src/interface-receiver.md +++ b/src/interface-receiver.md @@ -20,17 +20,22 @@ func (s *S) Write(str string) { s.data = str } +// We cannot get pointers to value stored in maps. sVals := map[int]S{1: {"A"}} -// You can only call Read using a value +// We can call Read on values stored in the map because Read +// has a value receiver. sVals[1].Read() -// This will not compile: +// We cannot call Write on values stored in the map because Write +// has a pointer receiver, and it's not possible to get a pointer +// to a value stored in a map. +// // sVals[1].Write("test") sPtrs := map[int]*S{1: {"A"}} -// You can call both Read and Write using a pointer +// You can call both Read and Write if the map stores pointers. sPtrs[1].Read() sPtrs[1].Write("test") ``` diff --git a/style.md b/style.md index 9d0382b3..8d03647f 100644 --- a/style.md +++ b/style.md @@ -216,17 +216,22 @@ func (s *S) Write(str string) { s.data = str } +// We cannot get pointers to value stored in maps. sVals := map[int]S{1: {"A"}} -// You can only call Read using a value +// We can call Read on values stored in the map because Read +// has a value receiver. sVals[1].Read() -// This will not compile: +// We cannot call Write on values stored in the map because Write +// has a pointer receiver, and it's not possible to get a pointer +// to a value stored in a map. +// // sVals[1].Write("test") sPtrs := map[int]*S{1: {"A"}} -// You can call both Read and Write using a pointer +// You can call both Read and Write if the map stores pointers. sPtrs[1].Read() sPtrs[1].Write("test") ``` From 0e359bd2a32c1251aeb8ffad416a6330eecbcd53 Mon Sep 17 00:00:00 2001 From: Abhinav Gupta Date: Fri, 3 Mar 2023 10:34:48 -0800 Subject: [PATCH 2/3] Apply suggestions from code review Co-authored-by: Matt Way --- src/interface-receiver.md | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/interface-receiver.md b/src/interface-receiver.md index 0d7e3733..7addf4ea 100644 --- a/src/interface-receiver.md +++ b/src/interface-receiver.md @@ -20,11 +20,13 @@ func (s *S) Write(str string) { s.data = str } -// We cannot get pointers to value stored in maps. +// We cannot get pointers to values stored in maps, because they are not +// addressable values. sVals := map[int]S{1: {"A"}} // We can call Read on values stored in the map because Read -// has a value receiver. +// has a value receiver, which does not require the value to +// be addressable. sVals[1].Read() // We cannot call Write on values stored in the map because Write @@ -35,7 +37,8 @@ sVals[1].Read() sPtrs := map[int]*S{1: {"A"}} -// You can call both Read and Write if the map stores pointers. +// You can call both Read and Write if the map stores pointers, +// because pointers are intrinsically addressable. sPtrs[1].Read() sPtrs[1].Write("test") ``` From 6387abd06dabaa78a387a96825a7ec2a9ae716af Mon Sep 17 00:00:00 2001 From: Abhinav Gupta Date: Fri, 3 Mar 2023 10:35:19 -0800 Subject: [PATCH 3/3] make style.md --- style.md | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/style.md b/style.md index 8d03647f..f4a9d189 100644 --- a/style.md +++ b/style.md @@ -216,11 +216,13 @@ func (s *S) Write(str string) { s.data = str } -// We cannot get pointers to value stored in maps. +// We cannot get pointers to values stored in maps, because they are not +// addressable values. sVals := map[int]S{1: {"A"}} // We can call Read on values stored in the map because Read -// has a value receiver. +// has a value receiver, which does not require the value to +// be addressable. sVals[1].Read() // We cannot call Write on values stored in the map because Write @@ -231,7 +233,8 @@ sVals[1].Read() sPtrs := map[int]*S{1: {"A"}} -// You can call both Read and Write if the map stores pointers. +// You can call both Read and Write if the map stores pointers, +// because pointers are intrinsically addressable. sPtrs[1].Read() sPtrs[1].Write("test") ```