golang / go

The Go programming language
https://go.dev
BSD 3-Clause "New" or "Revised" License
123.89k stars 17.65k forks source link

proposal: spec: extensions #70190

Closed BlueFalconHD closed 4 hours ago

BlueFalconHD commented 5 hours ago

Go Programming Experience

Intermediate

Other Languages Experience

Python, Swift, JS, Rust, TS, Java, Kotlin, C, C++

Related Idea

Has this idea, or one like it, been proposed before?

No, I don’t think so. While there have been discussions about adding methods to types from other packages, Go currently doesn’t allow defining methods on types not declared in the same package. This proposal is different because it introduces “extensions” as a formal language feature, allowing developers to add methods to any type, including those from external packages and built-in types.

Does this affect error handling?

No, this proposal doesn’t affect error handling.

Is this about generics?

No, this isn’t related to generics.

Proposal

The proposed change is to add a new feature called “extensions” to the Go language. This would let developers add new methods to existing types, even if those types are defined in other packages or are built-in types. It helps developers by letting them enhance types they don’t own without changing the original source code or making wrapper types. This makes code more reusable, easier to read, and reduces extra code.

Language Spec Changes

The language specification would need to be updated to include extension declarations. This means introducing new syntax for declaring extensions, possibly using a keyword like extension. It would allow defining methods on types not declared in the same package. The spec would also need to explain how extensions work, like being limited to the package where they’re declared, and how methods from extensions are used, especially if there are name conflicts. Any limitations, like not allowing extensions on certain types, would also need to be described.

Informal Change

Extensions let you add new methods to existing types, even if those types come from another package or are built-in. This can make your code more expressive and easier to maintain. For example, if you often need to check if a slice of integers contains a specific value, you can add a Contains method directly to the []int type:

extension []int {
    func (s []int) Contains(value int) bool {
        for _, v := range s {
            if v == value {
                return true
            }
        }
        return false
    }
}

numbers := []int{1, 2, 3, 4, 5}
if numbers.Contains(3) {
    fmt.Println("Found 3 in the slice!")
}

This avoids the need for utility functions and makes your code more readable.

Is this change backward compatible?

Yes, it is backward compatible. It introduces a new feature without changing existing syntax or behavior, so existing programs would still work as they did before.

Orthogonality: How does this change interact or overlap with existing features?

This proposal complements existing features like methods and interfaces by providing a new way to extend types. It overlaps with utility functions and embedding but offers a more direct and expressive way to add functionality. The goal isn’t to improve performance but to enhance code expressiveness and make developers more productive. Performance would stay about the same as existing methods since extensions would be compiled into methods like any other.

Would this change make Go easier or harder to learn, and why?

It might make Go a bit harder to learn because it adds a new language feature. However, for developers familiar with languages that support extensions, like Swift or Kotlin, it could make Go more approachable. It adds a useful tool that can simplify certain coding patterns.

Cost Description

The costs include increasing the complexity of the language, which can make it harder for newcomers. Development tools like editors, linters, and debuggers would need to be updated to support extensions. There’s also the potential for naming conflicts if multiple packages define extensions with the same method names on the same types. The Go team would need to maintain this new feature and ensure it works well with future language changes.

Changes to Go ToolChain

Compiler, gofmt, goimports, gopls, vet, delve, godoc

Performance Costs

Small compile-time increase for extra parsing and type checking. Negligible runtime cost.

Prototype

A possible implementation would involve introducing a new keyword like extension followed by the type being extended. The parser would need to recognize and correctly parse the new extension declarations. The type checker would include methods from extensions in the method sets of the extended types within the package scope. Method resolution logic would need to account for extensions to ensure consistent behavior. Extensions could be limited to the package where they’re declared to prevent global conflicts and maintain encapsulation. Clear rules or compiler errors would need to be defined for situations where multiple extensions introduce methods with the same name on the same type. Tools like gofmt, goimports, and gopls would need updates to handle the new constructs properly. By keeping extensions scoped to the package where they’re declared, the implementation minimizes the risk of naming conflicts and maintains the integrity of the type system.

gabyhelp commented 5 hours ago

Related Issues and Documentation

(Emoji vote if this was helpful or unhelpful; more detailed feedback welcome in this discussion.)

seankhliao commented 4 hours ago

Duplicate of #21401