Menu
Coddy logo textTech

메서드 체이닝

Coddy GO 여정의 객체 지향 프로그래밍 섹션에 포함된 레슨. 107개 중 81번째.

Method chaining은 메서드가 수신자를 반환하여 하나의 문장에서 여러 메서드 호출을 서로 연결할 수 있도록 하는 기법입니다. 이 개념은 이미 Builder 패턴에서 살펴보았지만, 다양한 맥락에서 유용한 독립적인 개념이기도 합니다.

key는 각 메서드에서 구조체를 가리키는 포인터를 반환하는 것입니다:

type Query struct {
    table   string
    columns []string
    where   string
    limit   int
}

func (q *Query) Select(cols ...string) *Query {
    q.columns = cols
    return q
}

func (q *Query) From(table string) *Query {
    q.table = table
    return q
}

func (q *Query) Where(condition string) *Query {
    q.where = condition
    return q
}

func (q *Query) Limit(n int) *Query {
    q.limit = n
    return q
}

이제 이러한 호출을 fluently 연결할 수 있습니다:

query := &Query{}
query.Select("name", "email").From("users").Where("active = true").Limit(10)

이는 별도의 문장과 비교하면 거의 자연어처럼 읽힙니다. 메서드 체이닝은 연산이 다른 값을 반환할 필요 없이 객체를 구성하거나 수정할 때 가장 잘 작동합니다. 이는 query builder, configuration API, 그리고 테스트 assertion 라이브러리에서 흔히 사용됩니다.

each 메서드는 chain이 제대로 작동하도록 포인터 리시버를 사용하고 *StructType을 반환해야 한다는 점을 기억하세요.

challenge icon

챌린지

쉬움

메서드 체이닝을 사용하여 속성과 콘텐츠가 있는 HTML 태그를 구성하는 유창한 HTML element builder를 만들어 봅시다! 이는 메서드 체이닝의 실용적인 활용 예입니다. HTML element를 만들 때 거의 자연어처럼 읽히는 API를 작성하게 됩니다.

코드를 두 파일에 걸쳐 구성합니다:

  • element.go: 체이닝 가능한 메서드를 사용하여 HTML element builder를 Define합니다.

    태그 이름, 속성의 맵(string에서 string으로), 그리고 inner 콘텐츠를 저장하는 Element 구조체를 Create합니다. 각각 *Element를 반환하는 다음 체이닝 가능한 메서드를 Build합니다:

    • NewElement(tag string) - 주어진 태그 이름과 initialized (empty) attributes map으로 새로운 Element를 creates하는 constructor
    • Attr(key, value string) - element에 attribute를 Add합니다
    • ID(id string) - "id" attribute를 설정하는 convenience 메서드
    • Class(class string) - "class" attribute를 설정하는 convenience 메서드
    • Content(text string) - element의 inner content를 설정합니다

    HTML 문자열을 반환하는 Render() 메서드를 Add합니다. Attributes는 key를 기준으로 alphabetical 순서로 appear해야 합니다. Format은 다음과 같습니다:

    <tag attr1="value1" attr2="value2">content</tag>

    attributes가 없으면 <tag>content</tag>만 렌더링합니다. content가 없으면 <tag attr="value"></tag>를 렌더링합니다.

  • main.go: 메서드 체이닝을 사용하여 HTML element를 Build합니다.

    태그 이름을 읽은 다음, 수행할 operation의 개수를 읽습니다. 각 operation은 다음 중 하나입니다:

    • id 뒤에 ID 값
    • class 뒤에 class 값
    • attr 뒤에 attribute 이름과 값 (두 줄)
    • content 뒤에 content 텍스트

    모든 operation을 fluently 연결한 다음 렌더링된 HTML을 출력합니다.

다음 입력이 제공됩니다:

  • 1번째 줄: 태그 이름
  • 2번째 줄: operation 수
  • 이후 줄: operation 유형과 값(들)

예를 들어, 다음이 주어졌을 때:

div
3
id
container
class
main-content
content
Hello World

출력은 다음과 같아야 합니다:

<div class="main-content" id="container">Hello World</div>

그리고 다음이 주어졌을 때:

a
3
attr
href
https://example.com
attr
target
_blank
content
Click here

출력은 다음과 같아야 합니다:

<a href="https://example.com" target="_blank">Click here</a>

그리고 다음이 주어졌을 때:

input
2
attr
type
text
attr
placeholder
Enter name

출력은 다음과 같아야 합니다:

<input placeholder="Enter name" type="text"></input>

그리고 다음이 주어졌을 때:

p
1
content
Simple paragraph

출력은 다음과 같아야 합니다:

<p>Simple paragraph</p>

메서드 체이닝을 사용하면 읽기 쉬운 방식으로 element를 단계별로 Build할 수 있다는 점에 주목하세요. 각 메서드는 element를 수정하고 반환하므로 다음 메서드 호출을 직접 연결할 수 있습니다.

직접 해보기

package main

import (
	"bufio"
	"fmt"
	"os"
	"strconv"
)

func main() {
	scanner := bufio.NewScanner(os.Stdin)

	// 태그 이름 읽기
	scanner.Scan()
	tagName := scanner.Text()

	// 연산 개수 읽기
	scanner.Scan()
	numOps, _ := strconv.Atoi(scanner.Text())

	// 요소 생성
	element := NewElement(tagName)

	// 각 연산 처리
	for i := 0; i < numOps; i++ {
		scanner.Scan()
		operation := scanner.Text()

		// TODO: 연산 유형에 따라 적절한 메서드를 체이닝하세요
		// 연산은 "id", "class", "attr" 또는 "content"일 수 있습니다
		// - "id"의 경우: 다음 줄을 ID 값으로 읽기
		// - "class"의 경우: 다음 줄을 클래스 값으로 읽기
		// - "attr"의 경우: 다음 두 줄 읽기 (속성 이름, 그다음 값)
		// - "content"의 경우: 다음 줄을 콘텐츠 텍스트로 읽기
		// 메서드 체이닝을 사용하여 요소를 유창하게 빌드하세요

		_ = operation // 구현할 때 이 줄을 제거하세요
	}

	// 렌더링된 HTML 출력
	fmt.Println(element.Render())
}
quiz icon실력 점검

이 레슨에는 짧은 퀴즈가 포함되어 있습니다. 레슨을 시작해 문제를 풀고 진행 상황을 기록하세요.

객체 지향 프로그래밍의 모든 레슨

직접 연습해 보세요: 온라인 Go 컴파일러