I agree, and there's a clear benefit that it's harder to dereference a nil interface than a nil pointer, when that interface has no methods. The problem is that statically it doesn't tell you anything about the possible contained type.
In comparison, a pointer tells you exactly the type contained, but it must be exactly one type, and there's always a risk of accidentally deferencing a nil pointer. If one day, generics type-constraint interfaces could be used as regular interface types, that would be powerful: you could have a variable of type "interface { float64 | Status }" and know for sure that the value *must* be either nil, float64 or Status. Furthermore, you wouldn't be able to use the contained value without an explicit type assertion. On Wednesday, 6 April 2022 at 01:10:23 UTC+1 sam.a....@gmail.com wrote: > I get what you're saying, and for what it's worth, you're absolutely > correct. Something like above is a set of tradeoffs, and I guess all I can > assert is that it works for me. I do think it's a good design, given Go's > lack of a None<T> type to enforce well-defined behavior on a nil pointer > dereference, but it's an example of a well-designed API from the days > before generics, which safely respects nil/null values in the appropriate > context. > > For most of my use of the model, the types offered by the pgtype pacakge > are A. total overkill, and B. just an intermediate type to hold a value > between two boundaries that do understand null values, such as bridging an > RPC frontend and a SQL backend. > > If anything, it proves that Generics do simplify codebases, and that > well-defined, graceful null/nil handling is worth the effort. > On Tuesday, April 5, 2022 at 5:13:04 AM UTC-5 Brian Candler wrote: > >> I did look at the code briefly. The main thing I noticed was that the >> return type of float8.Get() was an interface{} - so it's up to the caller >> to check at runtime whether the value is nil, a float64, or a Status. >> >> So you're right, it's not that they are compile-time unsafe, but rather >> that you have to write type matching code at each use site. Within a given >> switch branch, it's safe. >> >> On Tuesday, 5 April 2022 at 07:29:09 UTC+1 sam.a....@gmail.com wrote: >> >>> Uh, you should check the code: >>> github.com/jackc/pgtype/blob/master/float8.go If you know what you have >>> and what you're dealing with, and if you actually check the error result, >>> you do get safety. If you don't know what you've got, or if you're >>> iterating through the values, then you end up hitting the sad, sad, >>> reflective path...for now. >>> On Saturday, April 2, 2022 at 4:37:36 AM UTC-5 Brian Candler wrote: >>> >>>> Correct repository path is: https://github.com/jackc/pgtype >>>> >>>> Interesting. These structs generally contain a Status value as well: >>>> >>>> type Int8 struct { >>>> Int int64 >>>> Status Status >>>> } >>>> >>>> where pgtype.go has: >>>> >>>> type Status byte >>>> >>>> const ( >>>> Undefined Status = iota >>>> Null >>>> Present >>>> ) >>>> >>>> They also have Set() and Get() methods, although these are not >>>> compiled-time type safe as they accept and return interface{} >>>> >>>> On Friday, 1 April 2022 at 17:40:42 UTC+1 sam.a....@gmail.com wrote: >>>> >>>>> >>>>> Thanks for clarifying that, @Brian. Yeah. It took a bit to warm up to >>>>> that approach, but the github.com/jackc/pgtypes convinced me that the >>>>> results were worth it. The benefits: A, package interpretation methods >>>>> with a piece of data, B, lazily valuate data when needed, and C, gain >>>>> introspective capability specific to the type and not using reflect >>>>> On Friday, April 1, 2022 at 4:47:32 AM UTC-5 Brian Candler wrote: >>>>> >>>>>> That wasn't literal code with anglebrackets - you're supposed to fill >>>>>> that in yourself. I think he meant something like: >>>>>> >>>>>> type fooString struct{ string } >>>>>> >>>>>> https://go.dev/play/p/4Q94xMZDciV >>>>>> >>>>>> What this is doing is *embedding* a string value into a struct; if >>>>>> you have not come across type embedding before then Google for the >>>>>> details. >>>>>> >>>>>> You still cannot use one of these types transparently as a string, >>>>>> but you can use >>>>>> x.string >>>>>> instead of >>>>>> string(x) >>>>>> to extract the value. >>>>>> >>>>>> On Friday, 1 April 2022 at 06:48:04 UTC+1 yan.z...@gmail.com wrote: >>>>>> >>>>>>> Hi Sam! Your solution does not seem to work: >>>>>>> >>>>>>> package main >>>>>>> >>>>>>> import( >>>>>>> "fmt" >>>>>>> "strconv" >>>>>>> ) >>>>>>> >>>>>>> type <Purpose> String struct{string} >>>>>>> >>>>>>> func (s String) print(){ >>>>>>> fmt.Println(s) >>>>>>> } >>>>>>> >>>>>>> func main() { >>>>>>> var a String ="hello, world\n" >>>>>>> >>>>>>> a.print() >>>>>>> >>>>>>> fmt.Println(strconv.ParseInt("78",10, 64)) >>>>>>> >>>>>>> var x String ="452" >>>>>>> >>>>>>> n, _ := strconv.ParseInt(x, 10, 64) >>>>>>> } >>>>>>> >>>>>>> 在2022年3月26日星期六 UTC+8 06:41:15<sam.a....@gmail.com> 写道: >>>>>>> >>>>>>>> >>>>>>>> My workaround like is something like `type <Purpose>String >>>>>>>> struct{string}. It can be reasonably treated as a string for most >>>>>>>> cases in >>>>>>>> which as string is needed, and it lets you convert back conveniently >>>>>>>> from >>>>>>>> any scope in which it's reasonable for your program to know the >>>>>>>> difference. >>>>>>>> On Friday, March 18, 2022 at 12:46:34 AM UTC-5 Henry wrote: >>>>>>>> >>>>>>>>> My own preference is to have a small number of methods and put the >>>>>>>>> general functionalities into functions. By putting the general >>>>>>>>> functionalities into functions, you allow code reuse. In >>>>>>>>> object-oriented >>>>>>>>> programming, you normally attach as many functionalities as possible >>>>>>>>> to >>>>>>>>> their corresponding types and achieve code reuse via inheritance. >>>>>>>>> Since Go >>>>>>>>> does not have inheritance, you can achieve a similar effect with >>>>>>>>> standalone >>>>>>>>> functions. >>>>>>>>> >>>>>>>>> On Friday, March 18, 2022 at 11:26:51 AM UTC+7 Ian Lance Taylor >>>>>>>>> wrote: >>>>>>>>> >>>>>>>>>> On Thu, Mar 17, 2022 at 7:17 PM Zhaoxun Yan <yan.z...@gmail.com> >>>>>>>>>> wrote: >>>>>>>>>> > >>>>>>>>>> > I just came across this taboo in golang - new methods cannot be >>>>>>>>>> added to an existing type: >>>>>>>>>> >>>>>>>>>> Yes. If we didn't have this prohibition, then the set of >>>>>>>>>> interfaces >>>>>>>>>> satisfied by a type would depend on which package was using the >>>>>>>>>> type. >>>>>>>>>> >>>>>>>>>> See the discussion at https://go.dev/issue/21401. >>>>>>>>>> >>>>>>>>>> Ian >>>>>>>>>> >>>>>>>>> -- You received this message because you are subscribed to the Google Groups "golang-nuts" group. To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscr...@googlegroups.com. To view this discussion on the web visit https://groups.google.com/d/msgid/golang-nuts/4019e780-8fca-4e5b-88e3-f9fdcd1d32a8n%40googlegroups.com.