以下如何干燥?

Typical example with added getName() function.

I wonder how can I do not write getName() for circle and rect twice?

package main

import "fmt"
import "math"

// Here's a basic interface for geometric shapes.
type geometry interface {
    area() float64
    perim() float64
    getName() string
}

// For our example we'll implement this interface on
// `rect` and `circle` types.
type rect struct {
    width, height float64
    name string
}
type circle struct {
    radius float64
    name string
}

// To implement an interface in Go, we just need to
// implement all the methods in the interface. Here we
// implement `geometry` on `rect`s.
func (r rect) area() float64 {
    return r.width * r.height
}
func (r rect) perim() float64 {
    return 2*r.width + 2*r.height
}
func (r rect) getName() string {
    return r.name
}

// The implementation for `circle`s.
func (c circle) area() float64 {
    return math.Pi * c.radius * c.radius
}
func (c circle) perim() float64 {
    return 2 * math.Pi * c.radius
}
func (c circle) getName() string {
    return c.name
}

// If a variable has an interface type, then we can call
// methods that are in the named interface. Here's a
// generic `measure` function taking advantage of this
// to work on any `geometry`.
func measure(g geometry) {
    fmt.Println(g)
    fmt.Println(g.area())
    fmt.Println(g.perim())
    fmt.Println(g.getName())
}

func main() {
    r := rect{width: 3, height: 4, name: "rect5"}
    c := circle{radius: 5, name: "circle2"}

    // The `circle` and `rect` struct types both
    // implement the `geometry` interface so we can use
    // instances of
    // these structs as arguments to `measure`.
    measure(r)
    measure(c)
}

You could - and potentially should - embed your geometry type in another struct type that includes the name. Unless the name is "circle" or "square" or what have you, the name isn't actually related in any way to the geometry itself. So you could have:

type namedGeometry struct {
    geometry
    name string
}

func (ng *namedGeometry) getName() string {
    return ng.name
}

Which would serve the same purpose, remain DRY, and maintain separation of concerns. With geometry embedded, you can still call the geometry methods on a namedGeometry instance.

I would take a similar approach to Adrian's, but I would instead embed a base type, which holds common functionality, in your other types e.g.

type baseShape struct {
    name string
}

func (s *baseShape) getName() string {
    return s.name
}

type rect struct {
    width, height float64
    baseShape
}

type circle struct {
    radius float64
    baseShape
}

After doing this, you only need to implement the functions that differ between the shapes on a per type basis.